hashicorp/terraform · error

encountered a malformed backend state file that contains…

Error message

encountered a malformed backend state file that contains state for both a 'backend' and a 'state_store' block

What it means

ParseBackendStateFile found a file containing BOTH a `backend` block and a `state_store` block. These are mutually exclusive configuration shapes — backends are the classic model, state_store is the newer model — so a file with both is malformed and Terraform refuses to guess which to use.

Solutions

  1. Inspect .terraform/terraform.tfstate and delete whichever block (`backend` or `state_store`) you did not intend to keep.
  2. Re-run `terraform init` to rewrite the file cleanly from your configuration.
  3. Restore from a backup taken before the corruption.

Example fix

# inspect
jq '{has_backend: (.backend!=null), has_state_store: (.state_store!=null)}' .terraform/terraform.tfstate

# regenerate cleanly
rm .terraform/terraform.tfstate
terraform init
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight: detect dual-block corruption before parsing
var probe struct {
    Backend   *json.RawMessage `json:"backend"`
    StateStore *json.RawMessage `json:"state_store"`
}
_ = json.Unmarshal(src, &probe)
if probe.Backend != nil && probe.StateStore != nil {
    return nil, errors.New("backend state file has both backend and state_store; delete one and re-init")
}

Prevention

When it happens

Trigger: A hand-merged or partially-rewritten .terraform/terraform.tfstate, or a buggy migration tool that appended a state_store section without removing the prior backend section.

Common situations: Manual file surgery, interrupted `terraform init` mid-rewrite, or a third-party state-management tool that wrote both shapes.

Understand the failure class

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/c47cc32d7f2a5239. Report an issue: GitHub.

Appendix: 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 d32a084675)