hashicorp/terraform · error

Unsupported path step %#v (%t)

Error message

Unsupported path step %#v (%t)

What it means

Thrown by jsonplan.encodePath in the default branch of the path-step type switch. cty officially defines only two path step types, cty.IndexStep and cty.GetAttrStep. Any other concrete type implementing cty.PathValue (or a nil step) reaches default and aborts serialization, because the JSON path format has no representation for it.

Solutions

  1. Align the Terraform and cty library versions.
  2. If you construct paths programmatically, ensure only IndexStep and GetAttrStep are used before passing to jsonplan.
  3. Report the step type (%T) printed in the message upstream.

Example fix

// before
default:
	return nil, fmt.Errorf("Unsupported path step %#v (%t)", step, step)

// after (skip nil/unknown steps or add the new step type's JSON form)
default:
	if step == nil {
		continue
	}
	return nil, fmt.Errorf("unsupported path step %T", step)
Defensive patterns

Strategy: type-guard

Type guard

func isKnownPathStep(s cty.PathStep) bool {
    switch s.(type) {
    case cty.IndexStep, cty.GetAttrStep:
        return true
    }
    return false
}

for _, s := range path {
    if !isKnownPathStep(s) {
        return fmt.Errorf("refusing to encode path with unsupported step %T", s)
    }
}

Prevention

When it happens

Trigger: A cty.Path is constructed with a step type other than IndexStep/GetAttrStep; a nil entry in the path slice; a newer cty version introduced a step type Terraform's encoder does not know.

Common situations: Terraform built against an incompatible cty version; third-party code that builds custom cty.Path values and passes them into the JSON plan APIs.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/d44f94ca22613aed. Report an issue: GitHub.

Appendix: source

Thrown at internal/command/jsonplan/plan.go:1082

func encodePath(path cty.Path) (json.RawMessage, error) {
	steps := make([]json.RawMessage, 0, len(path))
	for _, step := range path {
		switch s := step.(type) {
		case cty.IndexStep:
			key, err := ctyjson.Marshal(s.Key, s.Key.Type())
			if err != nil {
				return nil, fmt.Errorf("Failed to marshal index step key %#v: %s", s.Key, err)
			}
			steps = append(steps, key)
		case cty.GetAttrStep:
			name, err := json.Marshal(s.Name)
			if err != nil {
				return nil, fmt.Errorf("Failed to marshal get attr step name %#v: %s", s.Name, err)
			}
			steps = append(steps, name)
		default:
			return nil, fmt.Errorf("Unsupported path step %#v (%t)", step, step)
		}
	}
	return json.Marshal(steps)
}

View on GitHub (pinned to d32a084675)