hashicorp/packer · error

Can't tell if interpolation is done: %s

Error message

Can't tell if interpolation is done: %s

What it means

`isDoneInterpolating` uses `regexp.MatchString` with a fixed pattern (`{{\s*user\s*`.*`\s*}}`) to decide whether a user variable still contains a `{{user `...`}}` reference. The pattern is a compile-time constant, so in practice this error is nearly unreachable; it fires only if the regexp engine fails to match the string (e.g. pathological input causing a regexp execution error). `renderVarsRecursively` and tests propagate it immediately, aborting variable interpolation.

Source

Thrown at packer/core.go:906

					"required variable not set: %s", n))
			}
		}
	}

	// TODO: validate all builders exist
	// TODO: ^^ provisioner
	// TODO: ^^ post-processor

	return err
}

func isDoneInterpolating(v string) (bool, error) {
	// Check for whether the var contains any more references to `user`, wrapped
	// in interpolation syntax.
	filter := `{{\s*user\s*\x60.*\x60\s*}}`
	matched, err := regexp.MatchString(filter, v)
	if err != nil {
		return false, fmt.Errorf("Can't tell if interpolation is done: %s", err)
	}
	if matched {
		// not done interpolating; there's still a call to "user" in a template
		// engine
		return false, nil
	}
	// No more calls to "user" as a template engine, so we're done.
	return true, nil
}

func (c *Core) renderVarsRecursively() (*interpolate.Context, error) {
	ctx := c.Context()
	ctx.EnableEnv = true
	ctx.UserVariables = make(map[string]string)
	shouldRetry := true
	changed := false
	failedInterpolation := ""

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Read the wrapped inner error to identify why regexp.MatchString failed; it is not a template syntax problem.
  2. Retry the command once — regexp execution errors on fixed patterns are not expected to be deterministic user-facing failures.
  3. If reproducible, report it as a bug with the offending variable value; the pattern is a constant in packer/core.go and should never error.
Defensive patterns

Strategy: try-catch

Try / catch

// Go: propagate but recognize as internal
if err := core.Initialize(); err != nil {
    if strings.Contains(err.Error(), "Can't tell if interpolation is done") {
        return fmt.Errorf("internal interpolation check failed: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: `isDoneInterpolating(v)` is called from `renderVarsRecursively` (after a successful `interpolate.RenderRegex`) or from `TestIsDoneInterpolating`, and `regexp.MatchString(filter, v)` returns a non-nil error, which is wrapped as `Can't tell if interpolation is done: %s`.

Common situations: Extremely rare in practice: regexp engine errors on the fixed pattern are essentially impossible with normal variable values; would indicate an internal/runtime-level issue rather than user misconfiguration. Most likely encountered by SDK/plugin developers touching the regex or running unit tests.

Related errors


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