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
- 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.
- Retry init after transient network/timeout errors; remote state reads are often flaky under load.
- Verify backend credentials have read + (if locking) access to both the state object and the lock table.
- 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
- Ensure no stale process holds the state lock; use force-unlock only when safe.
- Give the backend read access plus lock-table access to the terraform credentials.
- Keep remote state objects versioned/backed-up so corrupt state can be restored.
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
- error uploading state: %v
- Error loading state: %s
- Error locking state: %s
- Failed to load state: %w
- consul lock was lost
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/04161508635e5b78.
Report an issue: GitHub.