hashicorp/terraform · error

Error refreshing state: %s

Error message

Error refreshing state: %s

What it means

Emitted by InitCommand.run when sMgr.RefreshState() fails after the state manager is successfully created (init_run.go:327-328). RefreshState reads the latest state from the backend; unlike the StateMgr construction error, this means the handle is open but reading/locking/decoding the state failed. The %s is the underlying error.

Source

Thrown at internal/command/init_run.go:328

	// on a previous run) we'll use the current state as a potential source
	// of provider dependencies.
	if back != nil {
		c.ignoreRemoteVersionConflict(back)
		workspace, err := c.Workspace()
		if err != nil {
			diags = diags.Append(fmt.Errorf("Error selecting workspace: %s", err))
			view.Diagnostics(diags)
			return 1
		}
		sMgr, sDiags := back.StateMgr(workspace)
		if sDiags.HasErrors() {
			diags = diags.Append(fmt.Errorf("Error loading state: %s", sDiags.Err()))
			view.Diagnostics(diags)
			return 1
		}

		if err := sMgr.RefreshState(); err != nil {
			diags = diags.Append(fmt.Errorf("Error refreshing state: %s", err))
			view.Diagnostics(diags)
			return 1
		}

		state = sMgr.State()
	}

	if initArgs.Get {
		modsOutput, modsAbort, modsDiags := c.getModules(ctx, path, initArgs.TestsDirectory, rootModEarly, initArgs.Upgrade, view, policyClient)
		diags = diags.Append(modsDiags)
		if modsAbort || modsDiags.HasErrors() {
			view.Diagnostics(diags)
			return 1
		}
		if modsOutput {
			// If we outputted information, then we need to output a newline
			// so that our success message is nicely spaced out from prior text.
			view.Spacer()

View on GitHub (pinned to c9def3e214)

Solutions

  1. If a lock is held by a stale process, identify and release it (`terraform force-unlock <lock-id>`) after confirming no live run holds it.
  2. Retry init after transient network/timeout errors; remote state reads are often flaky under load.
  3. Verify backend credentials have read + (if locking) access to both the state object and the lock table.
  4. If the state file is corrupt, restore the last known-good state object from backend versioning/backups, then retry.

Example fix

# before
$ terraform init   # state lock held by dead process
# after
$ terraform force-unlock <lock-id>
$ terraform init
Defensive patterns

Strategy: retry

Validate before calling

// Check for an existing state lock before init (S3+DynamoDB example).
if locked, id := getStateLockStatus(); locked {
    return fmt.Errorf("state locked by %s; resolve before init", id)
}

Try / catch

// Retry RefreshState failures a few times for transient network errors.
for i := 0; i < 3; i++ {
    if err := run("terraform", "init"); err == nil { break }
    time.Sleep(backoff(i))
}

Prevention

When it happens

Trigger: The backend state object exists and is reachable, but reading it fails: network timeout reading the remote state file, state lock acquisition failure (another run holds the lock), corrupt/unreadable state file bytes, KMS/encryption errors on the backend, or the state object is missing mid-read.

Common situations: Concurrent terraform runs contending for a state lock; remote state backend intermittently unreachable; state file truncated/corrupted from a prior interrupted write; expired cloud credentials during a long init; DynamoDB lock table issues on S3 backends.

Related errors


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