opentofu/opentofu · error
failed to decode backend config: %w
Error message
failed to decode backend config: %w
What it means
Raised by BackendState.ForPlan (internal/command/clistate/cli_state.go:95) when the backend configuration cached in the CLI state file (.terraform/terraform.tfstate) cannot be decoded with ctyjson.Unmarshal against the backend schema's implied type. The cached raw config JSON no longer matches what the current backend schema accepts, so building the plans.Backend value fails.
Source
Thrown at internal/command/clistate/cli_state.go:95
func (b *BackendState) SetConfig(val cty.Value, schema *configschema.Block) error {
ty := schema.ImpliedType()
buf, err := ctyjson.Marshal(val, ty)
if err != nil {
return err
}
b.ConfigRaw = buf
return nil
}
func (b *BackendState) ForPlan(schema *configschema.Block, workspaceName string) (*plans.Backend, error) {
if b == nil {
return nil, nil
}
configVal, err := b.Config(schema)
if err != nil {
return nil, fmt.Errorf("failed to decode backend config: %w", err)
}
return plans.NewBackend(b.Type, configVal, schema, workspaceName)
}
var ErrNoState = errors.New("no state")
type jsonVersionOnly struct {
Version int `json:"version"`
}
// ReadState reads the CLI state file format written by WriteState.
// dataDirOverridden should be true when the data directory was explicitly
// overridden (e.g. via TF_DATA_DIR).
func ReadState(src io.Reader, dataDirOverridden bool) (*CLIState, error) {
if f, ok := src.(*os.File); ok && f == nil {
return nil, ErrNoState
}
View on GitHub (pinned to 3561785c48)
Solutions
- Run 'tofu init -reconfigure' to rewrite the backend cache from the current configuration, then retry the plan
- If reconfigure is not wanted, remove the stale cache file (.terraform/terraform.tfstate) and run 'tofu init'
- Verify the backend block in the configuration has attribute names/types valid for the backend (typos produce unexpected-attribute values)
- Align all team/CI environments on one OpenTofu version so the cached schema matches
Example fix
# before tofu plan # Error: failed to decode backend config: ... # after tofu init -reconfigure tofu plan
Defensive patterns
Strategy: fallback
Validate before calling
// decode the cached config against the schema BEFORE planning:
if bs != nil && !bs.Empty() {
if _, err := bs.Config(backendSchema); err != nil {
// stale/incompatible cache: refresh instead of failing later
_ = runInitReconfigure()
}
} Try / catch
backend, err := b.ForPlan(schema, ws)
if err != nil {
if strings.Contains(err.Error(), "failed to decode backend config") {
// cache/schema drift: regenerate with 'tofu init -reconfigure', then retry once
backend, err = afterReinitForPlan(b, schema, ws)
}
if err != nil {
return err
}
} Prevention
- Run 'tofu init -reconfigure' after version upgrades or backend block changes
- Never share or commit .terraform directories between differing checkouts
- Pin one OpenTofu version across team and CI
When it happens
Trigger: ForPlan called with a schema whose ImpliedType differs from the type the cached ConfigRaw was marshalled with: running plan after OpenTofu changed the backend's schema between versions, after editing the backend block to a type with different attributes, or against a .terraform directory written by a different tool version.
Common situations: Upgrading or downgrading OpenTofu without re-running init; a teammate's .terraform directory committed or copied between checkouts with different backend configs; hand-edited cache files; switching between local and remote backend configs without -reconfigure.
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
- error: using a saved cloud plan when executing OpenTofu loca
- PlanOutPath set without also setting PlanOutBackend (this is
- %s "%s" name must not be empty and only contain A-Za-z0-9-_
- failed to parse address URL: %w
- no schema found for %s (in provider %s)
AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15).
Data as JSON: /api/errors/b89db125466bbabf.
Report an issue: GitHub.