hashicorp/terraform · error
Unhandled backend configuration state. This is a bug…
Error message
Unhandled backend configuration state. This is a bug. Please report this error with the following information. Backend Config Nil: %v Saved Backend Empty: %v StateStore Config Nil: %v Saved StateStore Empty: %v
What it means
A defensive default branch in the big switch over (backendConfig nil?, saved backend empty?, stateStoreConfig nil?, saved stateStore empty?) combinations. Every legitimate combination has an explicit case; reaching default means a combination the authors believed impossible occurred, so it is reported as a Terraform bug with the four boolean flags for triage.
Solutions
- Capture the four booleans from the message and report them to the OpenTofu issue tracker as instructed.
- Recover locally: back up then delete .terraform/terraform.tfstate and run `tofu init -reconfigure` to rebuild a clean cache.
- Audit the configuration to ensure exactly one of backend/state_store is configured, not both.
- If reproducing after a version change, note the versions in the bug report and check the migration matrix against your cache shape.
Example fix
// before: cache file has both Backend and StateStore populated tofu init # -> Unhandled backend configuration state. This is a bug. // after: reset the working-directory cache and reinitialize cleanly cp .terraform/terraform.tfstate /tmp/tfstate.bak rm .terraform/terraform.tfstate tofu init -reconfigure
Defensive patterns
Strategy: validation
Validate before calling
// Reject configs that could produce an unhandled combination before init.
func validateBackendVsStateStore(cfg *configs.Module) error {
if cfg.Backend != nil && cfg.StateStore != nil {
return fmt.Errorf("configuration declares both backend %q and state_store %q; choose one", cfg.Backend.Type, cfg.StateStore.Type)
}
return nil
}
// Also validate the cache file does not have both Backend and StateStore set.
func validateCacheNotBoth(cachePath string) error {
s, err := workdir.LoadBackendStateFile(cachePath)
if err != nil || s == nil { return err }
if s.Backend != nil && !s.Backend.Empty() && s.StateStore != nil && !s.StateStore.Empty() {
return fmt.Errorf("cache file has both backend and state_store; run 'tofu init -reconfigure'")
}
return nil
} Try / catch
// This is a bug branch; do not 'handle' silently. Surface the four booleans and
// advise reconfigure.
diags = diags.Append(fmt.Errorf(
"Unhandled backend configuration state (backendCfgNil=%v savedBackendEmpty=%v stateStoreCfgNil=%v savedStateStoreEmpty=%v); run 'tofu init -reconfigure'",
backendConfig == nil, s.Backend.Empty(), stateStoreConfig == nil, s.StateStore.Empty(),
)) Prevention
- Configure exactly one of backend/state_store, never both.
- After switching between backend and state_store, run `tofu init -reconfigure` to reset the cache.
- Never manually edit .terraform/terraform.tfstate to set Backend or StateStore fields.
When it happens
Trigger: Hit only when the four-way combination is one the switch does not list, e.g. both backendConfig and stateStoreConfig non-nil simultaneously, or both saved Backend and saved StateStore non-empty simultaneously (a corrupt cache file should not have both). Real triggers are cache-file corruption or a future code path that sets the config fields inconsistently.
Common situations: Working directory's .terraform/terraform.tfstate has both Backend and StateStore populated (manual edit or bug in a prior migration); a config has both a `backend` and a `state_store` block somehow parsed (which earlier validation should reject); downgrade/upgrade across a version that wrote a different cache shape.
Related errors
- attempted to encode a malformed backend state file; it…
- attempted to encode a malformed backend state file…
- attempted to encode a malformed backend state file; state…
- attempted to encode a malformed backend state file…
- attempted to encode a malformed backend state file; data is…
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/05b4e745fef0de7c.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/meta_backend.go:1305
return savedStateStore, diags
}
initReason, ssDiags := m.determineStateStoreInitReason(s.StateStore, stateStoreConfig, opts.Locks)
diags = diags.Append(ssDiags)
if ssDiags.HasErrors() {
return nil, diags
}
// Regardless of whether this code is invoked in an init or non-init command,
// we advise users to choose between:
// 1. terraform state migrate
// 2. terraform init -reconfigure
diags = diags.Append(errStateStoreInitDiag(initReason))
return nil, diags
default:
diags = diags.Append(fmt.Errorf(
"Unhandled backend configuration state. This is a bug. Please\n"+
"report this error with the following information.\n\n"+
"Backend Config Nil: %v\n"+
"Saved Backend Empty: %v\n"+
"StateStore Config Nil: %v\n"+
"Saved StateStore Empty: %v\n",
backendConfig == nil,
s.Backend.Empty(),
stateStoreConfig == nil,
s.StateStore.Empty(),
))
return nil, diags
}
}
// determineInitReason is used in non-Init commands to interrupt the command early and prompt users to instead run an init command.
// That prompt needs to include the reason why init needs to be run, and it is determined here.
//View on GitHub (pinned to d32a084675)