hashicorp/terraform · error

Error loading statefile

Error message

Error loading statefile: %w

What it means

getStateFromPath opens the user-supplied path argument with os.Open; any error (file does not exist, permission denied, not a file) is wrapped with %w. This fires when terraform show <path> is given a path that cannot be opened at all — distinct from a path that opens but is not a valid statefile (739).

Solutions

  1. Verify the path exists and is a file: ls -l <path>.
  2. Use an absolute path to avoid cwd-relative resolution issues.
  3. Ensure the invoking user has read permission (chmod/chown as needed).
  4. If the state was never written locally, point at the backend-managed state by running `terraform show` without a path argument.

Example fix

# before
terraform show ./tfstate/terraform.tfstate
# after: absolute, verified path
terraform show /home/user/proj/tfstate/terraform.tfstate
Defensive patterns

Strategy: validation

Validate before calling

// Check the path exists and is readable before passing to terraform show.
info, err := os.Stat(path)
if err != nil {
    return fmt.Errorf("state path %s cannot be opened: %w", path, err)
}
if info.IsDir() {
    return fmt.Errorf("state path %s is a directory, not a file", path)
}

Prevention

When it happens

Trigger: terraform show <path> where os.Open(path) returns a non-nil error — ENOENT (no such file), EACCES (permission denied), or the path is a directory.

Common situations: Typo in the state file path; relative path resolved from the wrong cwd; state file deleted or never written; running show as a user without read permission; pointing at a directory by mistake.

Related errors


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

Appendix: source

Thrown at internal/command/show.go:385

	config, buildDiags := terraform.BuildConfigWithGraph(
		rootMod,
		loader.ModuleWalker(),
		variables,
		configs.MockDataLoaderFunc(loader.LoadExternalMockData),
	)
	diags = diags.Append(buildDiags)
	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())
	}

View on GitHub (pinned to d32a084675)