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

  1. Remove the self-edge: find where the vertex adds itself as a dependency and skip it (if src == dst, don't add)
  2. Fix name resolution so a component's own name in its prereq list is ignored rather than turned into an edge
  3. 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

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.