hashicorp/terraform · error

invalid syntax: %w

Error message

invalid syntax: %w

What it means

Thrown by ParseBackendStateFile during the first-pass JSON decode of the backend state file (.terraform/terraform.tfstate backend metadata). json.Unmarshal of just the version field failed, meaning the file content is not valid JSON at all. The %w is the json error (syntax error, truncated file, etc.).

Source

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

// Returns an error if the content is not valid syntax, or if the file is
// of an unsupported format version.
//
// This does not immediately decode the embedded backend config, and so
// it's possible that a subsequent call to [BackendConfigState.Config] will
// return further errors even if this call succeeds.
func ParseBackendStateFile(src []byte) (*BackendStateFile, error) {
	// To avoid any weird collisions with as-yet-unknown future versions of
	// 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 {

View on GitHub (pinned to c9def3e214)

Solutions

  1. Restore from the backup file (.terraform/terraform.tfstate.backup) if present.
  2. If the backend is remote, delete the corrupt local backend metadata and re-run `terraform init` to regenerate it.
  3. Validate the file is well-formed JSON with a linter before re-running.
  4. Re-run `terraform init -reconfigure` to rebuild backend state from config.

Example fix

# before: corrupt .terraform/terraform.tfstate
# invalid syntax: invalid character '\x00' looking for beginning of value

# after: restore from backup, or regenerate
cp .terraform/terraform.tfstate.backup .terraform/terraform.tfstate
terraform init
Defensive patterns

Strategy: validation

Validate before calling

// before parsing, validate the backend state file is valid JSON
func isValidJSON(path string) error {
    raw, err := os.ReadFile(path)
    if err != nil { return err }
    var probe map[string]json.RawMessage
    return json.Unmarshal(raw, &probe)
}

Type guard

// type guard: confirm the file is JSON before parsing as backend state
func looksLikeBackendState(raw []byte) bool {
    var probe struct{ Version int `json:"version"` }
    return json.Unmarshal(raw, &probe) == nil
}

Prevention

When it happens

Trigger: Any command that reads the backend state file when that file is not valid JSON: truncated by a crash, binary/corrupt content, manually edited and broken, or written by an incompatible tool.

Common situations: Terraform process killed mid-write leaving a partial file; file synced incompletely from network storage; editor saved it as text with BOM/CRLF issues; another tool overwrote it; disk corruption.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/8de06fa186028408. Report an issue: GitHub.