hashicorp/terraform · error

unsupported backend state version

Error message

unsupported backend state version %d; you may need to use Terraform CLI v%s to work in this directory

What it means

ParseBackendStateFile found a `version` field but it is not 3 — the only JSON backend-state format Terraform/OpenTofu knows how to read. The message reports the offending version and the TFVersion recorded in the file (the version of Terraform that wrote it), pointing the user to that binary for compatibility.

Solutions

  1. Upgrade the binary to at least the TFVersion printed in the message (or to the version that wrote the file).
  2. If you must downgrade, run `terraform init` on the newer version first, then `terraform state push`/`pull` to migrate state to a backend the older version understands.
  3. Start a fresh workspace: rm -rf .terraform and re-init on the desired version.

Example fix

# before — older terraform rejects newer backend state file

terraform version  # upgrade to >= the TFVersion in the error message
terraform init
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight: gate on supported version
var sniff struct {
    Version   int    `json:"version"`
    TFVersion string `json:"terraform_version"`
}
_ = json.Unmarshal(src, &sniff)
if sniff.Version != 3 {
    return nil, fmt.Errorf("backend state v%d written by terraform %s; use that version or re-init", sniff.Version, sniff.TFVersion)
}

Type guard

func isSupportedBackendVersion(src []byte) bool {
    var s struct{ Version int `json:"version"` }
    _ = json.Unmarshal(src, &s)
    return s.Version == 3
}

Prevention

When it happens

Trigger: A backend state file produced by a future Terraform version that bumped the format number, or by an incompatible fork. Reading the file with an older build.

Common situations: Downgrading Terraform/OpenTofu after a newer release wrote state, sharing a workspace across major versions, or a CI image pinned to an older version than developers' machines.

Related errors


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

Appendix: source

Thrown at internal/command/workdir/backend_state.go:93

	type VersionSniff struct {
		Version   int    `json:"version"`
		TFVersion string `json:"terraform_version,omitempty"`
	}
	var versionSniff VersionSniff
	err := json.Unmarshal(src, &versionSniff)
	if err != nil {
		return nil, fmt.Errorf("invalid syntax: %w", err)
	}
	if versionSniff.Version == 0 {
		// This could either mean that it's explicitly "version": 0 or that
		// the version property is missing. We'll assume the latter here
		// because state snapshot version 0 was an encoding/gob binary format
		// rather than a JSON format and so it would be very weird for
		// that to show up in a JSON file.
		return nil, fmt.Errorf("invalid syntax: no format version number")
	}
	if versionSniff.Version != 3 {
		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")

View on GitHub (pinned to d32a084675)