CloudFormation Error Guide: 'Circular dependency between resources' — Break the Reference Cycle
Fix CloudFormation 'Circular dependency between resources' by breaking Ref and GetAtt cycles with standalone association resources and careful DependsOn.
- #iac
- #infrastructure-as-code
- #troubleshooting
- #errors
Stuck on this Infrastructure as Code error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
Before provisioning, CloudFormation builds a dependency graph from every Ref, Fn::GetAtt, and DependsOn, then topologically sorts it to pick a creation order. If the graph contains a cycle, no valid order exists and the stack fails at validation:
Circular dependency between resources: [InstanceSecurityGroup, DatabaseSecurityGroup, InstanceSecurityGroupIngress]
The bracketed list is the set of resources CloudFormation could not order because each depends, directly or transitively, on another in the set.
Symptoms
create-stack/update-stackfails almost immediately withCircular dependency between resources: [...].- No resources are created (or the update rolls back) because validation happens before provisioning.
- The named resources reference each other through
Ref/GetAtt, often two security groups or a resource and its own association. - Adding a
DependsOnto “fix” ordering made it worse.
Common Root Causes
- Mutual security-group references — SG-A allows ingress from SG-B while SG-B allows ingress from SG-A, each inlined in the group’s own
SecurityGroupIngress. - Resource ↔ association cycle — a resource references an association that references the resource (route tables, gateway attachments, target group registrations).
DependsOnfighting an implicitRef— a manualDependsOnpointing back at something that alreadyRefs this resource.- Outputs/inputs looping through nested stacks — a child output feeds a parent value that feeds the child.
- IAM role ↔ resource — a role that references a resource ARN whose policy references the role.
Diagnostic Workflow
Validate the template locally to get the exact cycle members fast:
aws cloudformation validate-template --template-body file://template.yaml
Lint for dependency issues, which flags many cycles with line numbers:
cfn-lint template.yaml
Extract every dependency edge so you can see the loop:
# list all Ref / GetAtt / DependsOn usages
grep -nE 'Ref|Fn::GetAtt|GetAtt|DependsOn' template.yaml
For each resource named in the error, write down what it references and what references it; the cycle is where those two lists overlap. Render the graph if the template is large:
cfn-flip template.yaml template.json # normalize, then inspect programmatically
Example Root Cause Analysis
A template defined two security groups. InstanceSecurityGroup had an inline SecurityGroupIngress referencing DatabaseSecurityGroup, and DatabaseSecurityGroup had an inline ingress referencing InstanceSecurityGroup. Each group needed the other to exist first to resolve the Ref, so CloudFormation reported Circular dependency between resources: [InstanceSecurityGroup, DatabaseSecurityGroup].
The fix was to remove the mutual inline ingress rules and express the relationship with standalone AWS::EC2::SecurityGroupIngress resources. A standalone ingress resource can reference both groups by GroupId and SourceSecurityGroupId after both groups are created, so the two groups no longer depend on each other — they each depend only on nothing, and the two ingress resources depend on both groups. The cycle became a valid DAG and the stack deployed.
Prevention Best Practices
- Express bidirectional relationships (SG-to-SG ingress, associations) as standalone resources, not inline in the resources they connect.
- Avoid inline
SecurityGroupIngress/Egressbetween two groups; use separateAWS::EC2::SecurityGroupIngressresources. - Add
DependsOnonly to add ordering, never to resolve a data dependency thatRefalready implies. - Run
cfn-lintin CI to catch cycles before deploy. - Keep nested-stack outputs one-directional; do not feed a child output back into that child.
Quick Command Reference
aws cloudformation validate-template --template-body file://template.yaml
cfn-lint template.yaml
grep -nE 'Ref|Fn::GetAtt|DependsOn' template.yaml
cfn-flip template.yaml template.json
Conclusion
A circular dependency means CloudFormation’s resource graph has no valid creation order because two or more resources reference each other. The durable fix is structural: break the mutual reference by pulling the relationship into a standalone resource (typically a separate ingress or association) that depends on both endpoints instead of making the endpoints depend on each other. Validate and lint in CI so cycles are caught before they ever reach a deploy.
Fixed it? Get 500 Infrastructure as Code & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Stuck on this? Start guided troubleshooting
Open an interactive diagnostic session with this error already loaded. Work a step-by-step plan, record what each check returns, land on a root cause, and export a clean incident summary — no account needed to start.
Did this fix your issue?
Solved it a different way?
Share the fix that worked for you — reviewed, then published to help the next engineer.
That looks like it may contain a secret (key, token, password, or connection string). Please remove it — a note with a detected secret can’t be published.
Thanks — that helps. Published notes appear after a quick review.
Trending errors this week
The error guides other engineers are actually reading right now.
- 1mount: wrong fs type, bad option, bad superblock
- 2Docker 'failed to set up container networking': Fix the Bridge and IP Pool
- 3Docker 'failed to create shim task': How to Fix the containerd Runtime Error
- 4Transport endpoint is not connected
- 5modprobe: FATAL: Module not found
- 6mount: wrong fs type, bad option, bad superblock
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.