{"record":{"id":"05b4e745fef0de7c","repo":"hashicorp/terraform","slug":"unhandled-backend-configuration-state-this-is-a-b","errorCode":null,"errorMessage":"Unhandled backend configuration state. This is a bug. Please\nreport this error with the following information.\n\nBackend Config Nil: %v\nSaved Backend Empty: %v\nStateStore Config Nil: %v\nSaved StateStore Empty: %v\n","messagePattern":"Unhandled backend configuration state\\. This is a bug\\. Please\nreport this error with the following information\\.\n\nBackend Config Nil: (.+?)\nSaved Backend Empty: (.+?)\nStateStore Config Nil: (.+?)\nSaved StateStore Empty: (.+?)\n","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/meta_backend.go","lineNumber":1305,"sourceCode":"\n\t\t\treturn savedStateStore, diags\n\t\t}\n\n\t\tinitReason, ssDiags := m.determineStateStoreInitReason(s.StateStore, stateStoreConfig, opts.Locks)\n\t\tdiags = diags.Append(ssDiags)\n\t\tif ssDiags.HasErrors() {\n\t\t\treturn nil, diags\n\t\t}\n\n\t\t// Regardless of whether this code is invoked in an init or non-init command,\n\t\t// we advise users to choose between:\n\t\t// 1. terraform state migrate\n\t\t// 2. terraform init -reconfigure\n\t\tdiags = diags.Append(errStateStoreInitDiag(initReason))\n\t\treturn nil, diags\n\n\tdefault:\n\t\tdiags = diags.Append(fmt.Errorf(\n\t\t\t\"Unhandled backend configuration state. This is a bug. Please\\n\"+\n\t\t\t\t\"report this error with the following information.\\n\\n\"+\n\t\t\t\t\"Backend Config Nil: %v\\n\"+\n\t\t\t\t\"Saved Backend Empty: %v\\n\"+\n\t\t\t\t\"StateStore Config Nil: %v\\n\"+\n\t\t\t\t\"Saved StateStore Empty: %v\\n\",\n\t\t\tbackendConfig == nil,\n\t\t\ts.Backend.Empty(),\n\t\t\tstateStoreConfig == nil,\n\t\t\ts.StateStore.Empty(),\n\t\t))\n\t\treturn nil, diags\n\t}\n}\n\n// determineInitReason is used in non-Init commands to interrupt the command early and prompt users to instead run an init command.\n// That prompt needs to include the reason why init needs to be run, and it is determined here.\n//","sourceCodeStart":1287,"sourceCodeEnd":1323,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/command/meta_backend.go#L1287-L1323","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: cache file has both Backend and StateStore populated\ntofu init  # -> Unhandled backend configuration state. This is a bug.\n\n// after: reset the working-directory cache and reinitialize cleanly\ncp .terraform/terraform.tfstate /tmp/tfstate.bak\nrm .terraform/terraform.tfstate\ntofu init -reconfigure","handlingStrategy":"validation","validationCode":"// Reject configs that could produce an unhandled combination before init.\nfunc validateBackendVsStateStore(cfg *configs.Module) error {\n    if cfg.Backend != nil && cfg.StateStore != nil {\n        return fmt.Errorf(\"configuration declares both backend %q and state_store %q; choose one\", cfg.Backend.Type, cfg.StateStore.Type)\n    }\n    return nil\n}\n\n// Also validate the cache file does not have both Backend and StateStore set.\nfunc validateCacheNotBoth(cachePath string) error {\n    s, err := workdir.LoadBackendStateFile(cachePath)\n    if err != nil || s == nil { return err }\n    if s.Backend != nil && !s.Backend.Empty() && s.StateStore != nil && !s.StateStore.Empty() {\n        return fmt.Errorf(\"cache file has both backend and state_store; run 'tofu init -reconfigure'\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// This is a bug branch; do not 'handle' silently. Surface the four booleans and\n// advise reconfigure.\ndiags = diags.Append(fmt.Errorf(\n    \"Unhandled backend configuration state (backendCfgNil=%v savedBackendEmpty=%v stateStoreCfgNil=%v savedStateStoreEmpty=%v); run 'tofu init -reconfigure'\",\n    backendConfig == nil, s.Backend.Empty(), stateStoreConfig == nil, s.StateStore.Empty(),\n))","preventionTips":["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."],"tags":["backend","state-store","bug","cache-file","internal"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}