hashicorp/terraform · error
invalid step with type %#v
Error message
invalid step %q with type %#v
What it means
Returned by pathFromFlatmapKeyValue when the current type at this position in the path is primitive (string, number, bool) but the flatmap key still has more segments to consume. A primitive has no further navigable structure, so any suffix (e.g. '.foo' or '.0') is invalid — the path is trying to descend into a leaf.
Solutions
- Inspect the full flatmap key — the suffix after the primitive attribute is spurious and should be removed.
- If the attribute was supposed to be an object/collection, restore or correct the schema type so descent is valid.
- Regenerate the diff/RequiresReplace list against the current schema so keys match the actual type structure.
- Validate flatmap keys against the schema before persisting them.
Example fix
// before: flatmap key 'name.first' where 'name' is cty.String // after: flatmap key 'name' (no further descent on a primitive)
Defensive patterns
Strategy: validation
Validate before calling
func flatmapKeyRespectsPrimitiveLeaf(key string, ty cty.Type) bool {
// Walk the type tree segment-by-segment; if a primitive is reached and key has remaining segments, fail.
return canDescend(key, ty)
}
func canDescend(key string, ty cty.Type) bool {
_, rest := pathSplit(key)
if rest == "" { return true }
if ty.IsPrimitiveType() { return false }
// recurse into object/tuple/map/list/set as appropriate
return true
} Type guard
func keyIsValidForType(key string, ty cty.Type) bool {
_, rest := pathSplit(key)
if rest == "" { return true }
return !ty.IsPrimitiveType()
} Prevention
- Build flatmap keys from typed path objects rather than string concatenation to avoid over-descending past primitives.
- Regenerate diffs/RequiresReplace after changing an attribute from object to primitive type.
- Validate flatmap keys against the schema before persisting them.
When it happens
Trigger: Calling pathFromFlatmapKeyValue (transitively from requiresReplacePath or any flatmap-key-to-cty-path helper) with a key like 'attr.leaf.deeper' where 'attr' resolves to a cty.String. The decoder walked into 'attr', found a primitive type, but still has 'leaf.deeper' left over.
Common situations: Diff or RequiresReplace keys built by string concatenation that appended extra segments beyond the leaf; schema change that turned an object-typed attribute into a primitive while old keys still descend into it; misformatted flatmap keys from custom producers.
Related errors
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/6517984d4d101e8f.
Report an issue: GitHub.
Appendix: source
Thrown at internal/configs/hcl2shim/paths.go:136
if rest == "" {
return path, nil
}
p, err := pathFromFlatmapKeyValue(rest, ty)
if err != nil {
return path, err
}
return append(path, p...), nil
}
func pathFromFlatmapKeyValue(key string, ty cty.Type) (cty.Path, error) {
var path cty.Path
var err error
switch {
case ty.IsPrimitiveType():
err = fmt.Errorf("invalid step %q with type %#v", key, ty)
case ty.IsObjectType():
path, err = pathFromFlatmapKeyObject(key, ty.AttributeTypes())
case ty.IsTupleType():
path, err = pathFromFlatmapKeyTuple(key, ty.TupleElementTypes())
case ty.IsMapType():
path, err = pathFromFlatmapKeyMap(key, ty)
case ty.IsListType():
path, err = pathFromFlatmapKeyList(key, ty)
case ty.IsSetType():
path, err = pathFromFlatmapKeySet(key, ty)
default:
err = fmt.Errorf("unrecognized type: %s", ty.FriendlyName())
}
if err != nil {
return path, err
}
View on GitHub (pinned to d32a084675)