hashicorp/packer · error

unsupported refstring %q, must be of 'data', 'local' or 'var

Error message

unsupported refstring %q, must be of 'data', 'local' or 'var' type

What it means

NewRefStringFromDep converts an hcl.Traversal dependency (e.g. local.foo, var.bar, data.type.name) into a refString. Only the root scopes 'local', 'var', and 'data' are supported; a traversal rooted with any other identifier (or a malformed traversal missing the expected attribute segments) reaches the default case and returns this error. Callers are detectBuildPrereqDependencies and evaluateLocalVariables while scanning template expressions for build-prerequisite dependencies.

Source

Thrown at hcl2template/types.refstring.go:50

	// For locals/vars this is the name of the variable to look for, while
	// for datasources this is the name of the block, which coupled with the
	// type is the identity of the datasource's execution.
	Name string
}

func NewRefStringFromDep(t hcl.Traversal) (refString, error) {
	root := t.RootName()

	switch root {
	case "local", "var":
		return NewRefString(fmt.Sprintf("%s.%s", root, t[1].(hcl.TraverseAttr).Name))
	case "data":
		return NewRefString(fmt.Sprintf("%s.%s.%s", root,
			t[1].(hcl.TraverseAttr).Name,
			t[2].(hcl.TraverseAttr).Name))
	}

	return refString{}, fmt.Errorf("unsupported refstring %q, must be of 'data', 'local' or 'var' type", t)
}

func NewRefString(rs string) (refString, error) {
	parts := strings.Split(rs, ".")

	switch parts[0] {
	case "local", "var":
		return refString{
			MType: parts[0],
			Name:  parts[1],
		}, nil
	case "data":
		return newDataSourceRefString(parts)
	}

	return refString{}, fmt.Errorf("unsupported reftype %q, must be either 'data', 'local' or 'var'", parts[0])
}

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Fix the reference root to one of the supported forms: `local.<name>`, `var.<name>`, or `data.<type>.<name>`
  2. Check for plurals/case typos: `vars` → `var`, `locals` → `local`
  3. If you meant a special value like packer.version or pathroot, reference it via the correct Packer context variable instead of expecting dependency tracking
  4. Run `packer validate` to catch unsupported references with source locations before building

Example fix

// before: unsupported root in a local expression
local "tag" { value = vars.environment }   // 'vars' unsupported
// after
local "tag" { value = var.environment }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure dependency roots are only local/var/data before relying on
// prerequisite evaluation. Scan traversals in datasource/local expressions:
// valid roots regex: ^(local|var|data)\.
// e.g. grep -nE '(^|[^a-zA-Z_.])(vars|locals|pathroot)\.' *.pkr.hcl
// to flag unsupported roots.

Type guard

func isSupportedDepRoot(t hcl.Traversal) bool {
    switch t.RootName() {
    case "local", "var", "data":
        return true
    }
    return false
}

Try / catch

rs, err := NewRefStringFromDep(traversal)
if err != nil {
    return fmt.Errorf("dependency %v is not trackable; use local.<name>, var.<name> or data.<type>.<name>: %w", traversal, err)
}

Prevention

When it happens

Trigger: An expression inside a local or datasource traversal rooted at an unsupported scope — e.g. referencing a build artifact, pathroot, packer, or a mis-typed root like 'vars'/'Local' — gets passed to NewRefStringFromDep. Also produced when the traversal lacks the second attribute (t[1]) for local/var or third attribute (t[2]) for data, causing an index panic before this return in pathological cases.

Common situations: Typing `vars.foo` or `locals.foo` instead of `var.foo` / `local.foo` in a template; referencing special Packer contexts (packer.version, pathroot) in a position where dependency detection runs; hand-written HCL fragments with unusual traversals.

Related errors


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