hashicorp/terraform · error

Error reading as a statefile

Error message

Error reading %s as a statefile: %w

What it means

After successfully opening the file, getStateFromPath calls statefile.Read to decode it. If decoding fails the error is wrapped with the offending path. This means the file exists and is readable but its contents are not a recognizable Terraform state format (or are a corrupted/truncated state).

Solutions

  1. Confirm the file is a state file and not a plan: `terraform show` auto-detects plans only when given a plan file path, so ensure you pass the actual .tfstate for state.
  2. Restore from .tfstate.backup if the primary state is corrupt: cp terraform.tfstate.backup terraform.tfstate.
  3. Inspect the inner %w error for the exact decode failure (JSON syntax, version mismatch).
  4. If the state is from an incompatible version, use the matching Terraform version or terraform state pull to fetch fresh remote state.

Example fix

# before: pointing at a corrupt/empty state
terraform show ./terraform.tfstate
# after: restore from backup
cp ./terraform.tfstate.backup ./terraform.tfstate
terraform show ./terraform.tfstate
Defensive patterns

Strategy: type-guard

Validate before calling

// Sniff the file before decoding to give a clearer error.
func looksLikeState(path string) bool {
    b, err := os.ReadFile(path)
    if err != nil { return false }
    return bytes.Contains(b, []byte("\"version\":")) || bytes.Contains(b, []byte("version ="))
}

Type guard

func isStateFile(path string) bool {
    f, err := os.Open(path)
    if err != nil { return false }
    defer f.Close()
    var peek map[string]any
    return json.NewDecoder(f).Decode(&peek) == nil && peek["version"] != nil
}

Try / catch

// If decoding fails, fall back to the backup sibling file.
if _, err := getStateFromPath(path); err != nil {
    backup := path + ".backup"
    if _, bErr := getStateFromPath(backup); bErr == nil {
        log.Printf("primary state unreadable, used %s", backup)
    }
}

Prevention

When it happens

Trigger: terraform show <path> where os.Open succeeds but statefile.Read(file) returns an error — JSON/parse failure, unsupported state format version, truncated bytes, or the file is not a state file at all (e.g. a plan file or arbitrary JSON).

Common situations: Pointing `terraform show` at a binary plan file (use the plan path without extension handling) or a tfvars/json file; state file truncated by an interrupted write; state format from a much older/newer Terraform version; accidentally pointing at a backup .tfstate.backup that is partially written.

Related errors


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

Appendix: source

Thrown at internal/command/show.go:392

	if buildDiags.HasErrors() {
		return nil, diags
	}

	return config, diags
}

// getStateFromPath returns a statefile if the user-supplied path points to a statefile.
func getStateFromPath(path string) (*statefile.File, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("Error loading statefile: %w", err)
	}
	defer file.Close()

	var stateFile *statefile.File
	stateFile, err = statefile.Read(file)
	if err != nil {
		return nil, fmt.Errorf("Error reading %s as a statefile: %w", path, err)
	}
	return stateFile, nil
}

// getStateFromBackend returns the State for the current workspace, if available.
func getStateFromBackend(b backend.Backend, workspace string) (*statefile.File, error) {
	// Get the state store for the given workspace
	stateStore, sDiags := b.StateMgr(workspace)
	if sDiags.HasErrors() {
		return nil, fmt.Errorf("Failed to load state manager: %w", sDiags.Err())
	}

	// Refresh the state store with the latest state snapshot from persistent storage
	if err := stateStore.RefreshState(); err != nil {
		return nil, fmt.Errorf("Failed to load state: %w", err)
	}

	// Get the latest state snapshot and return it

View on GitHub (pinned to d32a084675)