hashicorp/terraform · error
Failed to load state
Error message
Failed to load state: %s
What it means
In Meta.backendFromState (used only for `terraform init -backend=false`), RefreshState on the local backend-cache file failed. Unlike 661 this path returns a local backend when the file is absent (nil state is fine), so this error specifically means the file exists but cannot be read/parsed.
Solutions
- Read the inner %s for the parse/IO cause.
- Validate .terraform/terraform.tfstate is well-formed JSON; if corrupt, back it up, delete it, and re-init.
- Correct ownership/permissions on .terraform so the current user can read it.
- Re-run `tofu init -backend=false` after cleanup; a missing file is acceptable and yields a fresh local backend.
Example fix
// before tofu init -backend=false # .terraform/terraform.tfstate corrupt # -> Failed to load state // after rm .terraform/terraform.tfstate tofu init -backend=false
Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate the cache file before a -backend=false run.
func validateBackendCacheReadable(dataDir string) error {
p := filepath.Join(dataDir, DefaultStateFilename)
if _, err := os.Stat(p); errors.Is(err, os.ErrNotExist) { return nil }
b, err := os.ReadFile(p)
if err != nil { return err }
var raw json.RawMessage
return json.Unmarshal(b, &raw)
} Try / catch
if err := sMgr.RefreshState(); err != nil {
if errors.Is(err, os.ErrNotExist) {
// nil state is fine for backendFromState
} else {
diags = diags.Append(fmt.Errorf("Failed to load state (cache unreadable; run 'tofu init -reconfigure'): %s", err))
return nil, diags
}
} Prevention
- For -backend=false runs, ensure .terraform/terraform.tfstate is either absent or valid.
- Do not switch users between init and -backend=false commands.
- Keep .terraform on a reliable local filesystem.
When it happens
Trigger: sMgr.RefreshState() errors on the existing .terraform/terraform.tfstate during a -backend=false run. Triggers: corrupt JSON in the cache file, truncated write, permission denied, or an incompatible/unknown state snapshot version that the parser rejects.
Common situations: Running `tofu init -backend=false` (or any command forcing local backend) against a working dir whose cache file was corrupted by a crash, manual edit, or a different CLI version; read-only mount of .terraform; file owned by another user.
Related errors
- Failed to load the backend state file
- Error creating temporary directory
- Failed to load the backend state file when preparing to…
- Failed to set new workspace
- Unhandled backend configuration state. This is a bug…
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/bc825e1cc64e594e.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/meta_backend.go:1493
"Unable to determine state store init reason",
"This is a bug in Terraform and should be reported",
))
return nil, diags
}
// backendFromState returns the initialized (not configured) backend directly
// from the backend state. This should be used only when a user runs
// `terraform init -backend=false`. This function returns a local backend if
// there is no backend state or no backend configured.
func (m *Meta) backendFromState(_ context.Context) (backend.Backend, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
// Get the path to where we store a local cache of backend configuration
// if we're using a remote backend. This may not yet exist which means
// we haven't used a non-local backend before. That is okay.
statePath := filepath.Join(m.DataDir(), DefaultStateFilename)
sMgr := &clistate.LocalState{Path: statePath}
if err := sMgr.RefreshState(); err != nil {
diags = diags.Append(fmt.Errorf("Failed to load state: %s", err))
return nil, diags
}
s := sMgr.State()
if s == nil {
// no state, so return a local backend
log.Printf("[TRACE] Meta.Backend: backend has not previously been initialized in this working directory")
return backendLocal.New(), diags
}
// Depending on the contents of the backend state file,
// prepare a backend.Backend in the appropriate way.
var b backend.Backend
switch {
case !s.StateStore.Empty():
// state_store
log.Printf("[TRACE] Meta.Backend: working directory was previously initialized for %q state store", s.StateStore.Type)
var ssDiags tfdiags.Diagnostics
b, ssDiags = m.savedStateStore(sMgr) // Relies on the state manager's internal state being refreshed above.View on GitHub (pinned to d32a084675)