hashicorp/terraform · error
invalid step %q with type %#v
Error message
invalid step %q with type %#v
What it means
Returned by pathFromFlatmapKeyValue (paths.go:136) when the declared type for the current path segment is a primitive (string/number/bool) but there is still a remaining key segment to navigate into. You cannot descend into a primitive — there are no sub-attributes — so any further path step is invalid.
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 c9def3e214)
Solutions
- Compare the flatmap key depth against the schema: a primitive attribute must be a leaf — remove any extra '.N' or '.sub' segments on it.
- If the attribute legitimately became a collection, update the schema type and migrate the state key shape together.
- If the extra segment is spurious, clean the state file or re-apply to regenerate the diff.
- Pin the provider version matching the state if a schema type change caused the mismatch.
Example fix
// before — schema: name = cty.String // state key: "name.0" (cannot index into a string) // after — keep scalar keys flat "name": "my-instance"
Defensive patterns
Strategy: validation
Validate before calling
// Ensure primitive attributes are not given nested sub-keys
func noNestedPrimitiveKeys(keys []string, ty cty.Type) error {
for name, aty := range ty.AttributeTypes() {
if !aty.IsPrimitiveType() {
continue
}
for _, k := range keys {
if strings.HasPrefix(k, name+".") {
return fmt.Errorf("primitive attribute %s cannot have sub-key in %s", name, k)
}
}
}
return nil
} Type guard
func isLeafKey(key, attrName string, ty cty.Type) bool {
aty, ok := ty.AttributeTypes()[attrName]
if !ok {
return false
}
return aty.IsPrimitiveType() && !strings.Contains(strings.TrimPrefix(key, attrName+"."), ".")
} Prevention
- When changing an attribute from primitive to collection (or back), migrate state key shapes together.
- Avoid manual edits that introduce spurious dot-segments on scalar attributes.
- Keep provider schemas and state version-aligned.
When it happens
Trigger: Navigating a flatmap key like 'name.0' where the schema declares 'name' as a primitive cty.String. pathFromFlatmapKeyValue sees a non-empty rest segment while ty.IsPrimitiveType() is true, hitting the first case branch that returns this error.
Common situations: Schema changed a primitive attribute to a collection (or vice versa) so the flatmap key depth no longer matches. A diff/state key has extra dot-segments that imply nesting the schema doesn't support. Manually edited state introducing spurious sub-keys on a scalar.
Related errors
- [%s] %s
- attribute %q not found
- unrecognized type: %s
- index %s out of range in %#v
- error marshaling relevant attributes for external changes: %
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/6517984d4d101e8f.
Report an issue: GitHub.