hashicorp/terraform · error
invalid value for %q in state: %s
Error message
invalid value for %q in state: %s
What it means
Returned by hcl2ValueFromFlatmapPrimitive (flatmap.go:200) when a raw string value read from a legacy flatmap state map cannot be converted (via cty convert.Convert) into the declared primitive type. The code reads the string, wraps it as cty.StringVal, then converts to the target type; failure means the stored string is not a valid encoding of that type — i.e. the state data is inconsistent with the schema.
Source
Thrown at internal/configs/hcl2shim/flatmap.go:200
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 error
val := cty.StringVal(rawVal)
val, err = convert.Convert(val, ty)
if err != nil {
// This should never happen for _valid_ input, but flatmap data might
// be tampered with by the user and become invalid.
return cty.DynamicVal, fmt.Errorf("invalid value for %q in state: %s", key, err)
}
return val, nil
}
func hcl2ValueFromFlatmapObject(m map[string]string, prefix string, atys map[string]cty.Type) (cty.Value, error) {
vals := make(map[string]cty.Value)
for name, aty := range atys {
val, err := hcl2ValueFromFlatmapValue(m, prefix+name, aty)
if err != nil {
return cty.DynamicVal, err
}
vals[name] = val
}
return cty.ObjectVal(vals), nil
}
func hcl2ValueFromFlatmapTuple(m map[string]string, prefix string, etys []cty.Type) (cty.Value, error) {View on GitHub (pinned to c9def3e214)
Solutions
- Open the state file and inspect the key named in the message; correct the value to a valid literal for the attribute's declared type.
- If the schema type legitimately changed, write a state upgrader / MigrateState function to transform old values before they reach flatmap decoding.
- If the value is genuinely unknown, remove the offending resource instance from state (terraform state rm) and re-import it.
- Pin provider versions so the schema that wrote the state matches the schema reading it.
Example fix
// before — state has: "instance_count": "not-a-number" // schema says: Type: cty.Number // after — correct the literal in state.json "instance_count": "3"
Defensive patterns
Strategy: validation
Validate before calling
// Validate a flatmap primitive string before handing it to the shim
func validatePrimitive(raw string, ty cty.Type) error {
v, err := convert.Convert(cty.StringVal(raw), ty)
if err != nil {
return fmt.Errorf("value %q not coercible to %s: %w", raw, ty.FriendlyName(), err)
}
_ = v
return nil
} Type guard
func isCoerciblePrimitive(raw string, ty cty.Type) bool {
if !ty.IsPrimitiveType() {
return false
}
_, err := convert.Convert(cty.StringVal(raw), ty)
return err == nil
} Try / catch
val, err := hcl2shim.HCL2ValueFromFlatmap(m, key, ty)
if err != nil {
// log and substitute null rather than crashing a refresh/plan
log.Printf("[WARN] state value at %s is invalid (%v); using null", key, err)
return cty.NullVal(ty), nil
} Prevention
- Never hand-edit terraform.tfstate values; use terraform state commands or re-apply.
- When changing an attribute's type in a provider schema, always ship a state upgrader.
- Pin provider versions so the schema that wrote state matches the one reading it.
When it happens
Trigger: A flatmap state entry at the given key holds a string that cannot coerce to the schema's type (e.g. the schema says number but the state string is "abc", or the schema says bool but the value is "maybe"). Happens during state read/import/refresh when decoding legacy or externally-modified state.
Common situations: Manually editing the terraform.tfstate file and introducing a malformed value. A provider schema changed an attribute type (string→number) without a state migration. Third-party tools or older Terraform versions writing values in an unexpected format. State produced by a different provider version with a divergent schema.
Related errors
- invalid count value for %q in state: %s
- cannot decode %s from flatmap
- wrong number of values for %q in state: got %d, but need %d
- missing field in set: %s.%s
- No state file was found! State management commands require
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/d97ee9bafd5d6e59.
Report an issue: GitHub.