hashicorp/packer · error
Self reference: %s
Error message
Self reference: %s
What it means
Alongside multi-vertex cycle detection, Validate separately scans every edge for self-loops (e.Source() == e.Target()) and reports `Self reference: <vertex>`. A vertex that depends on itself cannot be scheduled, and is reported distinctly from the generic cycle message for easier diagnosis.
Source
Thrown at internal/dag/dag.go:50
// Look for cycles of more than 1 component
var err error
cycles := g.Cycles()
if len(cycles) > 0 {
for _, cycle := range cycles {
cycleStr := make([]string, len(cycle))
for j, vertex := range cycle {
cycleStr[j] = VertexName(vertex)
}
err = errors.Join(err, fmt.Errorf(
"Cycle: %s", strings.Join(cycleStr, ", ")))
}
}
// Look for cycles to self
for _, e := range g.Edges() {
if e.Source() == e.Target() {
err = errors.Join(err, fmt.Errorf(
"Self reference: %s", VertexName(e.Source())))
}
}
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 eb36e3c3e4)
Solutions
- Remove the self-edge: find where the vertex adds itself as a dependency and skip it (if src == dst, don't add)
- Fix name resolution so a component's own name in its prereq list is ignored rather than turned into an edge
- Dedupe the dependency list before constructing the graph
Example fix
// before
for _, dep := range deps(v) { g.Add(v, dep) } // dep may be v itself
// after
for _, dep := range deps(v) {
if dep == v { continue }
g.Add(v, dep)
} Defensive patterns
Strategy: validation
Validate before calling
for _, e := range g.Edges() {
if e.Source() == e.Target() {
return fmt.Errorf("self reference: %s", dag.VertexName(e.Source()))
}
} Try / catch
if err := g.Validate(); err != nil {
if strings.Contains(err.Error(), "Self reference:") {
return fmt.Errorf("component depends on itself: %w", err)
}
return err
} Prevention
- Skip edges where src == dst when building the graph
- Filter a component's own name out of its prerequisite list
- Deduplicate dependency lists before adding edges
- Add a unit test with a self-loop vertex to catch regressions
When it happens
Trigger: buildPrereqsDAG (or a test like TestAcyclicGraphValidate_cycleSelf) adds an edge from a vertex to itself, e.g. a component whose prerequisite list contains its own name.
Common situations: A build component accidentally naming itself as a prerequisite; name-resolution matching a component to itself when building the prereq map; copy-paste of an edge line without changing the source vertex.
Related errors
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/de65ed88cb34a472.
Report an issue: GitHub.