hashicorp/terraform · error
encountered a malformed backend state file that contains sta
Error message
encountered a malformed backend state file that contains state for both a 'backend' and a 'state_store' block
What it means
A single backend state file must describe EITHER a 'backend' block OR a 'state_store' block, never both (the two fields are mutually exclusive storage mechanisms). Seeing both at backend_state.go:110 means the file is internally inconsistent or corrupt.
Source
Thrown at internal/command/workdir/backend_state.go:111
return nil, fmt.Errorf("unsupported backend state version %d; you may need to use Terraform CLI v%s to work in this directory", versionSniff.Version, versionSniff.TFVersion)
}
// If we get here then we can be sure that this file at least _thinks_
// it's format version 3.
var stateFile BackendStateFile
err = json.Unmarshal(src, &stateFile)
if err != nil {
return nil, fmt.Errorf("invalid syntax: %w", err)
}
if stateFile.Backend == nil && stateFile.Remote != nil {
// It's very unlikely to get here, but one way it could happen is
// if this working directory was most recently used with Terraform v0.8
// or earlier, which didn't yet include the concept of backends.
// This error message assumes that's the case.
return nil, fmt.Errorf("this working directory uses legacy remote state and so must first be upgraded using Terraform v0.9")
}
if stateFile.Backend != nil && stateFile.StateStore != nil {
return nil, fmt.Errorf("encountered a malformed backend state file that contains state for both a 'backend' and a 'state_store' block")
}
if stateFile.StateStore != nil && stateFile.StateStore.ProviderSupplyMode == "" {
// Check for this, as lacking this data can cause problems later when an empty provider version
// is encountered. This error will make debugging much easier.
return nil, fmt.Errorf("encountered a malformed backend state file with a 'state_store' block that is missing the required 'provider_supply_mode' property")
}
return &stateFile, nil
}
func EncodeBackendStateFile(f *BackendStateFile) ([]byte, error) {
f.Version = 3 // we only support version 3
f.TFVersion = version.SemVer.String()
switch {
case f.Backend != nil && f.StateStore != nil:
return nil, fmt.Errorf("attempted to encode a malformed backend state file; it contains state for both a 'backend' and a 'state_store' block. This is a bug in Terraform and should be reported.")
case f.Backend == nil && f.StateStore == nil:View on GitHub (pinned to c9def3e214)
Solutions
- Open .terraform/terraform.tfstate, determine which storage mechanism is actually in use, and delete the other top-level block.
- Safest: remove .terraform/ and re-run 'terraform init' with the single correct configuration.
- Check source-control history of the file to understand how both blocks came to be written.
Example fix
// before — .terraform/terraform.tfstate contains both:
{ "version":3, "backend":{...}, "state_store":{...} }
Error: encountered a malformed backend state file that contains state for both a 'backend' and a 'state_store' block
// after — keep only the one your config uses:
{ "version":3, "state_store":{...} }
// or simply:
$ rm -rf .terraform && terraform init Defensive patterns
Strategy: validation
Validate before calling
// Reject a file that declares both storage mechanisms before calling ParseBackendStateFile.
func hasBothBackendAndStateStore(src []byte) bool {
var probe struct {
Backend *json.RawMessage `json:"backend"`
StateStore *json.RawMessage `json:"state_store"`
}
_ = json.Unmarshal(src, &probe)
return probe.Backend != nil && probe.StateStore != nil
} Type guard
null
Try / catch
null
Prevention
- Never hand-merge .terraform/terraform.tfstate.
- Choose one storage mechanism (backend OR state_store) per directory and document it.
- After any manual recovery, re-run 'terraform init' to normalize the file.
When it happens
Trigger: ParseBackendStateFile finds Backend != nil && StateStore != nil after a successful decode.
Common situations: Manual editing or git-merging of .terraform/terraform.tfstate spliced two configs together; a botched migration between the classic backend mechanism and the newer state_store mechanism; files copied between directories.
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
- unsupported backend state version %d; you may need to use Te
- this working directory uses legacy remote state and so must
- error loading state: %w
- failed to write state: %w
- blob metadata %q was empty
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/c47cc32d7f2a5239.
Report an issue: GitHub.