{"record":{"id":"f0d758a60ea5c3c7","repo":"hashicorp/terraform","slug":"cannot-decode-s-from-flatmap","errorCode":null,"errorMessage":"cannot decode %s from flatmap","messagePattern":"cannot decode (.+?) from flatmap","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configs/hcl2shim/flatmap.go","lineNumber":176,"sourceCode":"\nfunc hcl2ValueFromFlatmapValue(m map[string]string, key string, ty cty.Type) (cty.Value, error) {\n\tvar val cty.Value\n\tvar err error\n\tswitch {\n\tcase ty.IsPrimitiveType():\n\t\tval, err = hcl2ValueFromFlatmapPrimitive(m, key, ty)\n\tcase ty.IsObjectType():\n\t\tval, err = hcl2ValueFromFlatmapObject(m, key+\".\", ty.AttributeTypes())\n\tcase ty.IsTupleType():\n\t\tval, err = hcl2ValueFromFlatmapTuple(m, key+\".\", ty.TupleElementTypes())\n\tcase ty.IsMapType():\n\t\tval, err = hcl2ValueFromFlatmapMap(m, key+\".\", ty)\n\tcase ty.IsListType():\n\t\tval, err = hcl2ValueFromFlatmapList(m, key+\".\", ty)\n\tcase ty.IsSetType():\n\t\tval, err = hcl2ValueFromFlatmapSet(m, key+\".\", ty)\n\tdefault:\n\t\terr = fmt.Errorf(\"cannot decode %s from flatmap\", ty.FriendlyName())\n\t}\n\n\tif err != nil {\n\t\treturn cty.DynamicVal, err\n\t}\n\treturn val, nil\n}\n\nfunc hcl2ValueFromFlatmapPrimitive(m map[string]string, key string, ty cty.Type) (cty.Value, error) {\n\trawVal, exists := m[key]\n\tif !exists {\n\t\treturn cty.NullVal(ty), nil\n\t}\n\tif rawVal == UnknownVariableValue {\n\t\treturn cty.UnknownVal(ty), nil\n\t}\n\n\tvar err error","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/configs/hcl2shim/flatmap.go#L158-L194","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — decoding a dynamic-typed slot from flatmap\nval, err := hcl2shim.hcl2ValueFromFlatmapValue(flatmap, \"attr\", cty.DynamicPseudoType)\n\n// after — decode as concrete type, or skip the shim for dynamic slots\nval, err := hcl2shim.hcl2ValueFromFlatmapValue(flatmap, \"attr\", cty.String)","handlingStrategy":"type-guard","validationCode":"func isDecodableFromFlatmap(ty cty.Type) bool {\n    return ty.IsPrimitiveType() || ty.IsObjectType() || ty.IsTupleType() ||\n        ty.IsMapType() || ty.IsListType() || ty.IsSetType()\n}","typeGuard":"func isDecodableFromFlatmap(ty cty.Type) bool {\n    if ty == cty.DynamicPseudoType { return false }\n    return ty.IsPrimitiveType() || ty.IsObjectType() || ty.IsTupleType() ||\n        ty.IsMapType() || ty.IsListType() || ty.IsSetType()\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["flatmap","hcl2shim","state-decode","cty","go"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}