hashicorp/packer · error

Failed to interpolate %s: Please make sure that the variable

Error message

Failed to interpolate %s: Please make sure that the variable you're referencing has been defined; Packer treats all variables used to interpolate other user variables as required.

What it means

When a variable's default references another user variable that is not yet defined (`{{user `other`}}`), `renderVarsRecursively` retries up to 100 loops hoping the dependency resolves. If a pass completes with no variable changed (`!changed`) while some still need interpolation (`shouldRetry`), the reference can never be satisfied, and Packer aborts with this message, embedding the last failed `"key": "value"` pair. Packer deliberately treats variables used to interpolate other variables as required — they must exist somewhere (defaults, -var, var-file).

Source

Thrown at packer/core.go:1040

		if !shouldRetry {
			break
		}

		// Clear completed vars from sortedMap before next loop. Do this one
		// key at a time because the indices are gonna change ever time you
		// delete from the map.
		for _, k := range deleteKeys {
			for ind, kv := range sortedMap {
				if kv.Key == k {
					sortedMap = append(sortedMap[:ind], sortedMap[ind+1:]...)
					break
				}
			}
		}
	}

	if !changed && shouldRetry {
		return ctx, fmt.Errorf("Failed to interpolate %s: Please make sure that "+
			"the variable you're referencing has been defined; Packer treats "+
			"all variables used to interpolate other user variables as "+
			"required.", failedInterpolation)
	}

	return ctx, nil
}

func (c *Core) init() error {
	if c.variables == nil {
		c.variables = make(map[string]string)
	}
	// Go through the variables and interpolate the environment and
	// user variables
	ctx, err := c.renderVarsRecursively()
	if err != nil {
		return err
	}

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Give the referenced variable a `default` value in the template's variables block.
  2. Pass the missing variable at invocation: `packer build -var 'missing=value' ...` or add it to your var-file.
  3. Check the failed `"key": "value"` text in the error for a misspelled variable name inside `{{user `...`}}` and fix it.
  4. Look for cycles where two variables reference each other and break the loop by inlining a literal value.

Example fix

// before
"variables": {
  "ami_name": "{{user `env`}}-web-{{timestamp}}"
}
// after (provide 'env' or give it a default)
"variables": {
  "env": {"default": "dev"},
  "ami_name": "{{user `env`}}-web-{{timestamp}}"
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify every {{user `x`}} reference resolves to a defined or provided variable
for name, val := range variables {
    for _, ref := range userRefs(val) { // regex: {{\s*user\s*`(.*)`\s*}}
        if _, ok := providedVars[ref]; !ok {
            if v, ok := templateVars[ref]; !ok || v.Default == "" && v.Required {
                return fmt.Errorf("variable %s references undefined %s", name, ref)
            }
        }
    }
}

Try / catch

// Go: detect unresolved variable references
if err := core.Initialize(); err != nil {
    if strings.Contains(err.Error(), "Failed to interpolate") {
        return fmt.Errorf("missing user variable for interpolation: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: During `Core.init()`, variable A's value contains `{{user `B`}}`, B has no default and was not passed via `-var`/`-var-file`/environment, all retries exhaust without progress, so the `!changed && shouldRetry` branch returns the error with `failedInterpolation` showing the unresolved variable.

Common situations: Cyclical variable definitions (A references B, B references A); a typo in the referenced variable name so it doesn't match any defined variable; forgetting to pass a required dependency variable on the CLI or in the var-file; renaming a variable but not updating references to it; deep nesting exceeding the 100-iteration cap.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/e06ba3ed32194d29. Report an issue: GitHub.