hashicorp/terraform · error
Cycle
Error message
Cycle: %s
What it means
Returned by AcyclicGraph.Validate when one or more strongly-connected components of length >= 2 exist in the graph — i.e. a real cycle. The cycle is rendered as an indented list of vertex names, normalized to start from the shortest/lexicographically-first vertex for stable output. Multiple cycles are joined into the same error via errors.Join.
Solutions
- Read the cycle list in the error — it names every participating resource/module in dependency order.
- Break the cycle by removing the offending depends_on entry or restructuring the resources so the dependency is one-directional.
- If the cycle is between modules, flatten or restructure the module call hierarchy.
- Use 'terraform graph' to visualize the dependency graph and confirm the cycle is gone after the edit.
Example fix
// before: mutual dependency
resource "a" "x" { depends_on = [a.y] }
resource "a" "y" { depends_on = [a.x] }
// after: break the cycle
resource "a" "x" { }
resource "a" "y" { depends_on = [a.x] } Defensive patterns
Strategy: validation
Validate before calling
// Before calling Validate, ensure no multi-vertex cycle exists.
func hasCycle(g *dag.AcyclicGraph) bool {
return len(g.Cycles()) > 0
} Try / catch
if err := g.Validate(); err != nil {
// err lists every cycle as a vertex chain; surface to the user as a config error.
return fmt.Errorf("configuration has dependency cycles: %w", err)
} Prevention
- Avoid mutual depends_on between resources; make dependency direction explicit and one-way.
- Use 'terraform graph' to inspect the dependency graph after structural config changes.
- Audit module includes for indirect cycles.
When it happens
Trigger: Calling AcyclicGraph.Validate() on a graph whose edges form a cycle (A->B->A or longer). Surfaces during Terraform's plan/apply graph validation when resources depend on each other in a loop (e.g. two resources each depend on the other via depends_on or implicit references).
Common situations: Mutual depends_on between two resources; circular module includes; provider/resource dependency loops introduced by templating or refactoring; config edits that create indirect cycles through data sources.
Related errors
- Self reference
- a network issue prevented cloud configuration;
- action has config values with unsupported marks
- action has ephemeral config values, which are not supported…
- Attempted to find configured project
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/4f59418903def8df.
Report an issue: GitHub.
Appendix: source
Thrown at internal/dag/dag.go:238
// compare lexically.
first := 0
for i := 1; i < len(cycleStr); i++ {
if len(cycleStr[i]) < len(cycleStr[first]) {
first = i
continue
}
if len(cycleStr[i]) == len(cycleStr[first]) && cycleStr[i] < cycleStr[first] {
first = i
}
}
// pivot the slice around our new first index
if first > 0 {
cycleStr = append(cycleStr[first:], cycleStr[:first]...)
}
err = errors.Join(err, fmt.Errorf(
"Cycle:\n %s", strings.Join(cycleStr, "\n "),
))
}
}
// Look for cycles to self
for _, e := range g.Edges() {
if e.Source == e.Target {
err = errors.Join(err, fmt.Errorf(
"Self reference: %s", e.Source.Name()))
}
}
return err
}
// Cycles reports any cycles between graph nodes.
// Self-referencing nodes are not reported, and must be detected separately.View on GitHub (pinned to d32a084675)