hashicorp/terraform · error
invalid count value for %q in state: %s
Error message
invalid count value for %q in state: %s
What it means
Returned by hcl2ValueFromFlatmapTuple (flatmap.go:237) when the count marker string stored at prefix+"#" in the flatmap is not parseable as an integer via strconv.Atoi. In legacy flatmap, tuple/list containers store their length in a special '#'-suffixed key; a non-numeric value there means the state is corrupt or was written by incompatible code.
Source
Thrown at internal/configs/hcl2shim/flatmap.go:237
var vals []cty.Value
// if the container is unknown, there is no count string
listName := strings.TrimRight(prefix, ".")
if m[listName] == UnknownVariableValue {
return cty.UnknownVal(cty.Tuple(etys)), nil
}
countStr, exists := m[prefix+"#"]
if !exists {
return cty.NullVal(cty.Tuple(etys)), nil
}
if countStr == UnknownVariableValue {
return cty.UnknownVal(cty.Tuple(etys)), nil
}
count, err := strconv.Atoi(countStr)
if err != nil {
return cty.DynamicVal, fmt.Errorf("invalid count value for %q in state: %s", prefix, err)
}
if count != len(etys) {
return cty.DynamicVal, fmt.Errorf("wrong number of values for %q in state: got %d, but need %d", prefix, count, len(etys))
}
vals = make([]cty.Value, len(etys))
for i, ety := range etys {
key := prefix + strconv.Itoa(i)
val, err := hcl2ValueFromFlatmapValue(m, key, ety)
if err != nil {
return cty.DynamicVal, err
}
vals[i] = val
}
return cty.TupleVal(vals), nil
}
func hcl2ValueFromFlatmapMap(m map[string]string, prefix string, ty cty.Type) (cty.Value, error) {View on GitHub (pinned to c9def3e214)
Solutions
- Inspect the state file at the key reported in the message (it is the prefix); ensure the '#'-suffixed entry is a non-negative integer.
- If the container should be empty/unknown, set the count to "0" or remove stale keys so the earlier guards handle it.
- If the schema type changed, add a state migration to rewrite the length key before decoding.
- Regenerate the state by re-applying or re-importing the resource if the flatmap is unrecoverable.
Example fix
// before — state has: "config.#": "three" // after — flatmap length keys must be integers "config.#": "3"
Defensive patterns
Strategy: validation
Validate before calling
// Verify a tuple/list count key is a valid integer before decoding
func validFlatmapCount(m map[string]string, prefix string) bool {
s, ok := m[prefix+"#"]
if !ok || s == hcl2shim.UnknownVariableValue {
return true
}
n, err := strconv.Atoi(s)
return err == nil && n >= 0
} Type guard
func isIntegerCount(s string) bool {
if s == hcl2shim.UnknownVariableValue {
return true
}
n, err := strconv.Atoi(s)
return err == nil && n >= 0
} Prevention
- Treat the terraform.tfstate file as machine-generated; avoid manual edits to '#'-suffixed length keys.
- Run a state migration whenever a collection-typed attribute changes arity.
- Pin provider versions to keep the flatmap convention stable.
When it happens
Trigger: Decoding a tuple-typed attribute from flatmap where the '<prefix>#' key holds a non-integer string (e.g. empty, a word, or UnknownVariableValue that bypassed the earlier guard). Triggered during state read/refresh/import when the schema declares a tuple type.
Common situations: Hand-edited state files where a '#'-suffixed length key was altered. A schema changed from list to tuple (or vice versa) and the count key format changed. State written by a much older/newer Terraform version with a different flatmap convention.
Related errors
- invalid value for %q in state: %s
- wrong number of values for %q in state: got %d, but need %d
- cannot decode %s from flatmap
- index %s out of range in %#v
- missing field in set: %s.%s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/142b09162d0a0c17.
Report an issue: GitHub.