hashicorp/terraform · critical
Self reference: %s
Error message
Self reference: %s
What it means
Returned by AcyclicGraph.Validate() (dag.go:247) when an edge exists whose Source vertex equals its Target vertex — a vertex that depends on itself. Unlike multi-vertex cycles (detected separately via strongly connected components), self-loops are checked directly by iterating edges; a self-edge is always invalid in an acyclic graph.
Source
Thrown at internal/dag/dag.go:247
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.
func (g *AcyclicGraph) Cycles() [][]Vertex {
var cycles [][]Vertex
for _, cycle := range StronglyConnected(&g.Graph) {
if len(cycle) > 1 {
cycles = append(cycles, cycle)
}
}
return cycles
}View on GitHub (pinned to c9def3e214)
Solutions
- Read the vertex name in the message; find that resource/module in config and remove the self-reference (e.g. remove itself from its depends_on list).
- Run terraform graph and look for a node with an edge looping back to itself.
- If building the DAG programmatically, guard against adding Edge(v, v).
- Rename one of two colliding resources so the reference resolves to a distinct node.
Example fix
// before
resource "aws_instance" "web" {
depends_on = [aws_instance.web] // self reference
}
// after — remove the self reference
resource "aws_instance" "web" {
depends_on = [aws_instance.db]
} Defensive patterns
Strategy: validation
Validate before calling
// Reject self-edges before validating/walking the graph
func hasSelfEdge(g *dag.AcyclicGraph) bool {
for _, e := range g.Edges() {
if e.Source == e.Target {
return true
}
}
return false
} Type guard
func hasSelfEdge(g *dag.AcyclicGraph) bool {
for _, e := range g.Edges() {
if e.Source == e.Target {
return true
}
}
return false
} Prevention
- Never list a resource in its own depends_on.
- If building a DAG programmatically, guard g.Edge(v, v) before adding.
- Run Validate() on constructed graphs before Walk().
When it happens
Trigger: A resource or graph node has an edge pointing to itself (e.Source == e.Target). In Terraform terms, a resource whose depends_on or reference graph includes itself, or programmatic DAG construction that added Edge(v, v).
Common situations: A resource lists itself in depends_on. A module/resource name collision causing a reference to resolve to the same node. Programmatic graph builders that add an edge from a node to itself. Copy-paste in dependency wiring.
Related errors
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/ea7f34c430c6c0fa.
Report an issue: GitHub.