Search code examples
pythonamazon-web-servicesaws-cloudformationaws-glueaws-cdk

AWS CDK Resolution error: Unable to resolve object tree with circular reference


I have one stack (etl_stack_2.py) that initializes a Partner construct and an OrderWorkflow construct. So partner and OrderWorkFlow are siblings in the tree. partner has a job property that is used by OrderWorkFlow. When I run cdk ls I get a circular reference error:

$ cdk ls
jsii.errors.JavaScriptError: 
  Error: Resolution error: Resolution error: Unable to resolve object tree with circular reference. Path: /Resources/${Token[data-lake-etl-infra-dev.order_workflow-dev.order_workflow_start_trigger-dev.LogicalID.100]}/Properties/actions/0/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host.
  Object creation stack:
    at new Intrinsic (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/intrinsic.js:21:44)
    at new PostResolveToken (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/util.js:73:9)
    at Object.ignoreEmpty (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/util.js:33:12)
    at CfnTrigger._toCloudFormation (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/cfn-resource.js:237:44)
    at /private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/refs.js:100:74
    at Object.findTokens (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:128:13)
    at findAllReferences (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/refs.js:100:38)
    at Object.resolveReferences (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/refs.js:23:19)
    at Object.prepareApp (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/prepare-app.js:34:16)
    at Object.synthesize (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/synthesis.js:18:19)
    at App.synth (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/stage.js:78:41)
    at /Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7756:51
    at Kernel._wrapSandboxCode (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8405:20)
    at /Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7756:25
    at Kernel._ensureSync (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8381:20)
    at Kernel.invoke (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7755:26)
    at KernelHost.processRequest (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7456:28)
    at KernelHost.run (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7394:14)
    at Immediate._onImmediate (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7397:37)
    at processImmediate (internal/timers.js:456:21).
  Object creation stack:
    at new Intrinsic (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/intrinsic.js:21:44)
    at new PostResolveToken (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/util.js:73:9)
    at CfnTrigger._toCloudFormation (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/cfn-resource.js:235:39)
    at /private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/refs.js:100:74
    at Object.findTokens (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:128:13)
    at findAllReferences (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/refs.js:100:38)
    at Object.resolveReferences (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/refs.js:23:19)
    at Object.prepareApp (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/prepare-app.js:34:16)
    at Object.synthesize (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/synthesis.js:18:19)
    at App.synth (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/stage.js:78:41)
    at /Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7756:51
    at Kernel._wrapSandboxCode (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8405:20)
    at /Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7756:25
    at Kernel._ensureSync (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8381:20)
    at Kernel.invoke (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7755:26)
    at KernelHost.processRequest (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7456:28)
    at KernelHost.run (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7394:14)
    at Immediate._onImmediate (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7397:37)
    at processImmediate (internal/timers.js:456:21)
      at resolve (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:35:15)
      at Object.resolve (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:29:33)
      at resolve (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:113:43)
      at Object.resolve (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:29:33)
      at resolve (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:113:43)
      at Object.resolve (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:29:33)
      at resolve (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:113:43)
      at Object.resolve (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:29:33)
      at resolve (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:113:43)
      at Kernel._wrapSandboxCode (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8408:19)
      at /Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7756:25
      at Kernel._ensureSync (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8381:20)
      at Kernel.invoke (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7755:26)
      at KernelHost.processRequest (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7456:28)
      at KernelHost.run (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7394:14)
      at Immediate._onImmediate (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7397:37)
      at processImmediate (internal/timers.js:456:21)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "app.py", line 13, in <module>
    app.synth()
  File "/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/aws_cdk/core/__init__.py", line 11531, in synth
    return jsii.invoke(self, "synth", [options])
  File "/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_kernel/__init__.py", line 122, in wrapped
    return _recursize_dereference(kernel, fn(kernel, *args, **kwargs))
  File "/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_kernel/__init__.py", line 320, in invoke
    args=_make_reference_for_native(self, args),
  File "/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_kernel/providers/process.py", line 351, in invoke
    return self._process.send(request, InvokeResponse)
  File "/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_kernel/providers/process.py", line 321, in send
    raise JSIIError(resp.error) from JavaScriptError(resp.stack)
jsii.errors.JSIIError: Resolution error: Resolution error: Unable to resolve object tree with circular reference. Path: /Resources/${Token[data-lake-etl-infra-dev.order_workflow-dev.order_workflow_start_trigger-dev.LogicalID.100]}/Properties/actions/0/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host/node/host.
Object creation stack:
  at new Intrinsic (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/intrinsic.js:21:44)
  at new PostResolveToken (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/util.js:73:9)
  at Object.ignoreEmpty (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/util.js:33:12)
  at CfnTrigger._toCloudFormation (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/cfn-resource.js:237:44)
  at /private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/refs.js:100:74
  at Object.findTokens (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/resolve.js:128:13)
  at findAllReferences (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/refs.js:100:38)
  at Object.resolveReferences (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/refs.js:23:19)
  at Object.prepareApp (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/prepare-app.js:34:16)
  at Object.synthesize (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/private/synthesis.js:18:19)
  at App.synth (/private/var/folders/gd/gpl89dgn5f7c8mzqx3dc8hzh0000gr/T/jsii-kernel-hDzf8X/node_modules/@aws-cdk/core/lib/stage.js:78:41)
  at /Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7756:51
  at Kernel._wrapSandboxCode (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8405:20)
  at /Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7756:25
  at Kernel._ensureSync (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8381:20)
  at Kernel.invoke (/Users/honarmand/xyz/xyz-data-lake/data-lake-etl-infra/venv/lib/python3.7/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7755:26)
  at KernelHost.processRequest (/Users/

I'm not sure why this is happening or how to fix it. I would appreciate any insight. Here is my code:

app.py

from aws_cdk import core
from etl_stack_2 import EtlStack

app = core.App()
environments = ["dev", "staging", "pre-production", "production"]
for env in environments:
  EtlStack(app, id=f"data-lake-etl-infra-{env}", env=env)

app.synth()

etl_stack_2.py

from aws_cdk import (
  aws_s3 as s3,
  core
)
import yaml
from pathlib import Path
import os

from partner import Partner
from workflows.order_workflow import OrderWorkflow

class EtlStack(core.Stack):
  def __init__(self, scope: core.Construct, id: str, env: str,**kwargs) -> None:
    super().__init__(scope, id=id, **kwargs)

    assets_bucket = s3.Bucket.from_bucket_name(self, 'assets_bucket', "bucket_name")

    current_dir = os.path.dirname(os.path.abspath(__file__))
    scripts_root = str(Path(current_dir, "../..", "scripts").resolve())
    job_role = f"role-service-glue-{env}"

    partner = Partner(self,
      "id-123",
      env=env,
      assets_bucket=assets_bucket,
      scripts_root=scripts_root,
      job_role=job_role
    )

    OrderWorkflow(
      scope=self,
      id=f"order_workflow-{env}",
      env=env,
      partner_job=partner.job       # this is where I pass the job property to OrderWorkflow
    )

order_workflow.py

from aws_cdk import (
  aws_glue as glue,
  core
)

class OrderWorkflow(core.Construct):
  def __init__(self, scope: core.Construct, id: str, *,
               env: str,
               partner_job: glue.CfnJob,
               **kwargs):
    super().__init__(scope, id, **kwargs)

    order_workflow = glue.CfnWorkflow(
      scope=self,
      id=f"glue-order_workflow-{env}"
    )

    start_trigger = glue.CfnTrigger(
      scope=self,
      id=f"order_workflow_start_trigger-{env}",
      actions=[partner_job],     # If I pass [] to actions instead it works fine
      type="SCHEDULED",
      description="this schedules trigger starts the order workflow",
      name="Order Workflow start",
      schedule="cron(15 * * * ? *)",
      workflow_name=order_workflow.name
    )

Solution

  • In the OrderWorkflow, I pass [glue.CfnTrigger.ActionProperty(job_name=partner_job.ref)] to actions instead of [partner_job], and that solved the problem. So the start_trigger looks like:

    start_trigger = glue.CfnTrigger(
          scope=self,
          id=f"order_workflow_start_trigger-{env}",
          actions=[glue.CfnTrigger.ActionProperty(job_name=partner_job.ref)],
          type="SCHEDULED",
          description="this schedules trigger starts the order workflow",
          name="Order Workflow start",
          schedule="cron(15 * * * ? *)",
          workflow_name=order_workflow.name
    )
    

    If you look at CDK documentation on CfnTrigger, the actions property needs to be an ActionProperty: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-glue.CfnTrigger.html#construct-props