hashicorp/terraform · error
failed to lock state in Consul: %s
Error message
failed to lock state in Consul: %s
What it means
For non-default workspaces, StateMgr (backend_state.go:108) acquires a Consul lock to initialize an empty-state sentinel. If stateMgr.Lock fails (lock already held, Consul unreachable, session creation failure), the backend cannot proceed and returns this with the underlying lock error.
Source
Thrown at internal/backend/remote-state/consul/backend_state.go:108
}
if !b.lock {
stateMgr.DisableLocks()
}
// the default state always exists
if name == backend.DefaultStateName {
return stateMgr, nil
}
// Grab a lock, we use this to write an empty state if one doesn't
// exist already. We have to write an empty state as a sentinel value
// so States() knows it exists.
lockInfo := statemgr.NewLockInfo()
lockInfo.Operation = "init"
lockId, err := stateMgr.Lock(lockInfo)
if err != nil {
return nil, diags.Append(fmt.Errorf("failed to lock state in Consul: %s", err))
}
// Local helper function so we can call it multiple places
lockUnlock := func(parent error) error {
if err := stateMgr.Unlock(lockId); err != nil {
return fmt.Errorf(strings.TrimSpace(errStateUnlock), lockId, err)
}
return parent
}
// Grab the value
if err := stateMgr.RefreshState(); err != nil {
err = lockUnlock(err)
return nil, diags.Append(err)
}
// If we have no state, we have to create an empty stateView on GitHub (pinned to c9def3e214)
Solutions
- Wait for the other run to finish, or run `terraform force-unlock <id>` with the lock ID.
- Confirm the Consul agent is reachable and healthy.
- Reduce concurrent runs on the same workspace; enable locking only when needed.
Defensive patterns
Strategy: retry
Validate before calling
# confirm Consul is reachable and check for an existing lock entry
consul members >/dev/null 2>&1 || { echo "consul unreachable" >&2; exit 1; }
consul kv get -recurse tfstate/ | grep -q '/.lockinfo' \
&& echo "WARN: a lock info entry exists; another run may hold the lock" Try / catch
// retry StateMgr init on lock contention, then surface the lock error
var sm statemgr.Full
err := backoff.RetryNotify(func() error {
var d tfdiags.Diagnostics
sm, d = b.StateMgr(ws)
return d.Err()
}, backoff.NewExponentialBackOff(), func(e error, d time.Duration) {
log.Printf("consul lock busy, retrying in %s: %v", d, e)
}) Prevention
- Avoid concurrent terraform runs against the same workspace.
- Clear stale locks with force-unlock after a crash.
- Monitor Consul health before running.
When it happens
Trigger: Initializing a non-default Consul state workspace while another terraform process holds the lock, the Consul agent is down, or session creation/lock acquisition failed.
Common situations: Concurrent terraform runs against the same workspace; a stale lock left by a crashed run; Consul connectivity or ACL issues.
Related errors
- failed to lock azure state: %s
- state blob is already locked
- Error unlocking Consul state. Lock ID: %s Error: %s You ma
- state %q already locked
- LocalState not locked
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/e2303acc2aef9765.
Report an issue: GitHub.