hashicorp/terraform · error

invalid value for in state

Error message

invalid value for %q in state: %s

What it means

Returned by hcl2ValueFromFlatmapPrimitive when the raw string stored in the flatmap cannot be converted to the declared attribute type via cty's convert.Convert. The shim first wraps the raw string as cty.StringVal then attempts a conversion; if conversion fails (e.g. the string is not parseable as the target number/bool/list), it reports the offending state key plus the underlying conversion error. As the comment notes, this only triggers for tampered/corrupt state — well-formed state always converts cleanly.

Solutions

  1. Inspect the state key named in the error and the conversion error message — the value is malformed for the declared type.
  2. Restore the attribute from a known-good state backup rather than editing it by hand.
  3. If the schema type legitimately changed, write a state upgrader that migrates the value before the new schema is applied.
  4. Avoid manual edits to .tfstate; use 'terraform state' subcommands or import flows instead.

Example fix

// not a code fix — operational recovery
// before: state contains "size": "not-a-number" for a number-typed attribute
// after: restore from backup, or run a state upgrader that casts the value
Defensive patterns

Strategy: validation

Validate before calling

// Caller-side: verify the raw flatmap string coerces to the target type before invoking the shim.
func canConvertFlatmapString(raw string, ty cty.Type) bool {
    _, err := convert.Convert(cty.StringVal(raw), ty)
    return err == nil
}

Try / catch

if val, err := hcl2shim.HCL2ValueFromFlatmap(m, key, ty); err != nil {
    // Distinguish corrupt state from a real bug: re-decode as string and surface
    // a friendlier 'state value at <key> is malformed' message.
    log.Printf("state decode failed for %q: %v; falling back to manual repair", key, err)
    return repairOrAbort(key, err)
}

Prevention

When it happens

Trigger: Manually editing a state file and inserting a non-numeric string for an attribute whose schema type is number/bool; downgrading a provider whose new schema is stricter than the value persisted in state; restore of a state backup whose values were transformed by an external tool.

Common situations: Hand-edited .tfstate files; partial state corruption from disk failure or merge conflicts in remote state; switching a schema attribute from string to a stricter type while old state still holds incompatible values.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/d97ee9bafd5d6e59. Report an issue: GitHub.

Appendix: 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 d32a084675)