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 ret

View on GitHub (pinned to c9def3e214)

Solutions

  1. Run `terraform init -reconfigure` to rewrite the backend config state against the current schema.
  2. Delete the stale .terraform/terraform.tfstate backend metadata and re-init.
  3. Confirm the backend block in the config matches the backend type whose schema is being applied.
  4. 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

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

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/24394346dc5d123d. Report an issue: GitHub.