hashicorp/terraform · error
invalid syntax: no format version number
Error message
invalid syntax: no format version number
What it means
ParseBackendStateFile successfully parsed JSON but the top-level `version` field was 0 (the zero value), which means the field is missing entirely or explicitly null. Version 0 is impossible for JSON state (snapshot version 0 was gob-encoded binary), so this is treated as a malformed/unsupported file.
Solutions
- Confirm the file is meant to be a Terraform backend state file (it may have been overwritten by another tool).
- Delete the bogus file and `terraform init` to recreate it from the backend block.
- If migrating from another tool, write a proper backend "<type>" {} block and init instead.
Example fix
# before — .terraform/terraform.tfstate contains just {"backend":{...}}
# after — let terraform own the file
rm .terraform/terraform.tfstate
terraform init Defensive patterns
Strategy: validation
Validate before calling
// pre-flight: reject files missing the version field up front
var sniff struct{ Version int `json:"version"` }
_ = json.Unmarshal(src, &sniff)
if sniff.Version == 0 {
return nil, errors.New("backend state file lacks a version field; regenerate with `terraform init`")
} Type guard
func hasVersionField(src []byte) bool {
var s struct{ Version int `json:"version"` }
_ = json.Unmarshal(src, &s)
return s.Version != 0
} Prevention
- Don't write .terraform/terraform.tfstate from external tooling.
- If migrating tooling, delete the file and let `terraform init` recreate it.
When it happens
Trigger: A .terraform/terraform.tfstate file whose JSON is valid but lacks a numeric `version` key, e.g. a hand-rolled stub, a different tool's JSON, or a backend state produced by a fork that omits the version field.
Common situations: User-generated or third-party tool wrote a JSON file in .terraform/ without the schema Terraform expects; partial merge/clobber of the file.
Related errors
- Error copying state from the previous %[1]q %[2]s to the…
- argument is required
- Can't serialize backend configuration as JSON
- Can't serialize backend configuration as JSON
- encountered a malformed backend state file that contains…
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/a0295393b53a78ba.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/workdir/backend_state.go:90
// the format, we'll do a first pass of decoding just the "version"
// property, and then decode the rest only if we find the version number
// that we're expecting.
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")View on GitHub (pinned to d32a084675)