hashicorp/terraform · error
failed to decode backend config: %w
Error message
failed to decode backend config: %w
What it means
Thrown by BackendConfigState.PlanData when s.Config(schema) fails: Config does ctyjson.Unmarshal(s.ConfigRaw, ty) where ty is the schema's ImpliedType. Failure means the stored raw backend config bytes do not conform to the provided schema (type mismatch, unknown attribute, deprecated shape). The %w is the ctyjson unmarshal error. This runs while building the plan's backend representation.
Source
Thrown at internal/command/workdir/backend_config_state.go:86
return nil
}
// PlanData produces an alternative representation of the receiver that is
// suitable for storing in a plan. The current workspace must additionally
// be provided, to be stored alongside the backend configuration.
//
// The backend configuration schema is required in order to properly
// encode the backend-specific configuration settings.
//
// As backends are not implemented by providers, the provider schema argument should always be nil
func (s *BackendConfigState) PlanData(schema *configschema.Block, _ *configschema.Block, workspaceName string) (*plans.Backend, error) {
if s == nil {
return nil, nil
}
configVal, err := s.Config(schema)
if err != nil {
return nil, fmt.Errorf("failed to decode backend config: %w", err)
}
return plans.NewBackend(s.Type, configVal, schema, workspaceName)
}
func (s *BackendConfigState) DeepCopy() *BackendConfigState {
if s == nil {
return nil
}
ret := &BackendConfigState{
Type: s.Type,
Hash: s.Hash,
}
if s.ConfigRaw != nil {
ret.ConfigRaw = make([]byte, len(s.ConfigRaw))
copy(ret.ConfigRaw, s.ConfigRaw)
}
return retView on GitHub (pinned to c9def3e214)
Solutions
- Run `terraform init -reconfigure` to rewrite the backend config state against the current schema.
- Delete the stale .terraform/terraform.tfstate backend metadata and re-init.
- Confirm the backend block in the config matches the backend type whose schema is being applied.
- Read the wrapped %w for the specific attribute/type mismatch and correct config accordingly.
Example fix
# before: backend config state from old backend type # failed to decode backend config: ... # after terraform init -reconfigure
Defensive patterns
Strategy: validation
Validate before calling
// before PlanData, verify stored backend config matches current schema
func backendConfigMatchesSchema(raw json.RawMessage, schema *configschema.Block) error {
var v cty.Value
return ctyjson.Unmarshal(raw, schema.ImpliedType())
} Prevention
- Run `terraform init -reconfigure` after changing backend type or version.
- Don't hand-edit backend state metadata.
- Keep the .terraform dir in sync with the current config.
- Re-init after any backend schema-affecting upgrade.
When it happens
Trigger: Calling PlanData (during plan generation) when the persisted backend config (ConfigRaw in .terraform/.terraform/terraform.tfstate backend metadata) does not match the backend schema currently in use — e.g. after a backend type/version change without re-init, or a corrupt backend state file.
Common situations: Switched backend type (s3->cloud) without `terraform init -reconfigure`; backend schema changed between provider/terraform versions; hand-edited backend state; stale .terraform dir from a different config.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- saved backend configuration is invalid: %w
- Can't serialize backend configuration as JSON: %s
- Can't serialize backend configuration as JSON: %s
- can't show a saved cloud plan unless the current root module
- error: using a saved cloud plan when executing Terraform loc
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/24394346dc5d123d.
Report an issue: GitHub.