Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Infrastructure as Code By James Joyner IV · · 9 min read

CloudFormation Error Guide: 'Circular dependency between resources' — Break the Reference Cycle

Quick answer

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
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

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-stack fails almost immediately with Circular 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 DependsOn to “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).
  • DependsOn fighting an implicit Ref — a manual DependsOn pointing back at something that already Refs 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/Egress between two groups; use separate AWS::EC2::SecurityGroupIngress resources.
  • Add DependsOn only to add ordering, never to resolve a data dependency that Ref already implies.
  • Run cfn-lint in 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.

Free download · 368-page PDF

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.