hashicorp/terraform · error
cannot decode from flatmap
Error message
cannot decode %s from flatmap
What it means
Returned by hcl2ValueFromFlatmapValue when the target cty.Type does not match any handled branch (primitive, object, tuple, map, list, set). The function dispatches on type kind; reaching the default branch means the type is either cty.DynamicPseudoType, a nested dynamic, or an unrecognized type object — none of which can be decoded from the legacy flatmap (key/value string) representation.
Solutions
- Confirm the Type passed in is one of: primitive, object, tuple, map, list, or set — and that it is not cty.DynamicPseudoType at the top level.
- If the source data is genuinely dynamic, decode it as cty.String and convert afterwards instead of asking the shim to infer the type.
- For state migration, run through the proper state upgrader chain so the schema matches the data being decoded.
- Reproduce with a minimal flatmap + type pair to confirm which kind is falling through, then widen the switch if a legitimate new kind is required.
Example fix
// before — decoding a dynamic-typed slot from flatmap val, err := hcl2shim.hcl2ValueFromFlatmapValue(flatmap, "attr", cty.DynamicPseudoType) // after — decode as concrete type, or skip the shim for dynamic slots val, err := hcl2shim.hcl2ValueFromFlatmapValue(flatmap, "attr", cty.String)
Defensive patterns
Strategy: type-guard
Validate before calling
func isDecodableFromFlatmap(ty cty.Type) bool {
return ty.IsPrimitiveType() || ty.IsObjectType() || ty.IsTupleType() ||
ty.IsMapType() || ty.IsListType() || ty.IsSetType()
} Type guard
func isDecodableFromFlatmap(ty cty.Type) bool {
if ty == cty.DynamicPseudoType { return false }
return ty.IsPrimitiveType() || ty.IsObjectType() || ty.IsTupleType() ||
ty.IsMapType() || ty.IsListType() || ty.IsSetType()
} Prevention
- Never request flatmap decoding for cty.DynamicPseudoType; decode as a concrete type or skip the shim.
- When migrating state, route values through the state upgrader chain so types match the data.
- For dynamic payloads, store them as JSON-encoded strings and parse post-decode.
When it happens
Trigger: Calling hcl2ValueFromFlatmapValue (directly or via the flatmap round-trip helpers) with a Type whose top-level kind is dynamic or a recently added cty kind that the shim does not know. Most often reached during state migration or when shimming a v3 state schema into a typed cty value.
Common situations: State files written by an older Terraform version being read by newer code where a schema attribute became cty.DynamicPseudoType; custom flatmap producers (some external tools) emitting keys the shim cannot map; testing harnesses that feed synthetic flatmaps with mismatched types.
Related errors
- attribute not found
- index out of range in %#v
- invalid count value for
- invalid step with type %#v
- invalid value for in state
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/f0d758a60ea5c3c7.
Report an issue: GitHub.
Appendix: source
Thrown at internal/configs/hcl2shim/flatmap.go:176
func hcl2ValueFromFlatmapValue(m map[string]string, key string, ty cty.Type) (cty.Value, error) {
var val cty.Value
var err error
switch {
case ty.IsPrimitiveType():
val, err = hcl2ValueFromFlatmapPrimitive(m, key, ty)
case ty.IsObjectType():
val, err = hcl2ValueFromFlatmapObject(m, key+".", ty.AttributeTypes())
case ty.IsTupleType():
val, err = hcl2ValueFromFlatmapTuple(m, key+".", ty.TupleElementTypes())
case ty.IsMapType():
val, err = hcl2ValueFromFlatmapMap(m, key+".", ty)
case ty.IsListType():
val, err = hcl2ValueFromFlatmapList(m, key+".", ty)
case ty.IsSetType():
val, err = hcl2ValueFromFlatmapSet(m, key+".", ty)
default:
err = fmt.Errorf("cannot decode %s from flatmap", ty.FriendlyName())
}
if err != nil {
return cty.DynamicVal, err
}
return val, nil
}
func hcl2ValueFromFlatmapPrimitive(m map[string]string, key string, ty cty.Type) (cty.Value, error) {
rawVal, exists := m[key]
if !exists {
return cty.NullVal(ty), nil
}
if rawVal == UnknownVariableValue {
return cty.UnknownVal(ty), nil
}
var err errorView on GitHub (pinned to d32a084675)