hashicorp/terraform · error
failed to lock azure state: %s
Error message
failed to lock azure state: %s
What it means
Raised in Backend.StateMgr (backend_state.go:117-119) when initializing a brand-new workspace state blob. Because the blob does not yet exist, Terraform acquires a lease (client.Lock) to safely create it; if Lock returns an error (another process already holds the lease, or the lease acquire data-plane call failed), this error wraps the resulting statemgr.LockError which also carries the existing lock info.
Source
Thrown at internal/backend/remote-state/azure/backend_state.go:119
accountName: b.accountName,
snapshot: b.snapshot,
}
stateMgr := &remote.State{Client: client}
// Grab the value
if err := stateMgr.RefreshState(); err != nil {
return nil, diags.Append(err)
}
//if this isn't the default state name, we need to create the object so
//it's listed by States.
if v := stateMgr.State(); v == nil {
// take a lock on this state while we write it
lockInfo := statemgr.NewLockInfo()
lockInfo.Operation = "init"
lockId, err := client.Lock(lockInfo)
if err != nil {
return nil, diags.Append(fmt.Errorf("failed to lock azure state: %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 this isn't the default state name, we need to create the object so
//it's listed by States.
if v := stateMgr.State(); v == nil {View on GitHub (pinned to c9def3e214)
Solutions
- Wait for the other Terraform process to finish and release the lease, then retry
- Identify the lock holder and run 'terraform force-unlock <lock-id>' with the ID from the error message
- Use the Azure portal / az storage blob lease break to release a stale lease: az storage blob lease break --account-name <account> -c <container> -b <key>
- Ensure only one writer runs per workspace (CI queue/locking) to avoid contention
Example fix
# the error reports the existing lock info; force-unlock with its id terraform force-unlock a1b2c3d4-e5f6-7890-abcd-ef1234567890 # or break the lease directly in Azure az storage blob lease break \ --account-name mystage --auth-mode login \ -c tfstate -b "prod.terraform.tfstate"
Defensive patterns
Strategy: retry
Validate before calling
# Before opening a fresh workspace, check whether its state blob is lease-locked
KEY="${ARM_KEY}env:${WS_NAME}"
STATUS=$(az storage blob show --account-name "$ARM_STORAGE_ACCOUNT_NAME" -c "$ARM_CONTAINER_NAME" -n "$KEY" --query 'properties.lease.status' -o tsv 2>/dev/null)
[ "$STATUS" = "locked" ] && echo "WARN: blob already locked -> error 151 likely; wait or force-unlock" || echo "OK: not locked" Try / catch
# Bash: on lock failure, surface the lock id and offer force-unlock
run_with_lock_guard() {
if ! terraform "$@" 2>err.log; then
if grep -q "failed to lock azure state" err.log; then
LID=$(grep -oE '[0-9a-f-]{36}' err.log | head -1)
echo "State locked. Review holder, then: terraform force-unlock $LID"
fi
return 1
fi
} Prevention
- Serialize CI per workspace so only one run acquires the lease
- On a crashed run, inspect the lock info and force-unlock before retrying
- Use 'az storage blob lease status' checks in pipelines for shared workspaces
When it happens
Trigger: Produced at backend_state.go:117-119 the first time a non-existent workspace state is opened (e.g. 'terraform workspace new' or 'terraform init' for a fresh key) when client.Lock fails — typically because properties.LeaseStatus == Locked (error 154) or AcquireLease failed.
Common situations: Two concurrent 'terraform apply' runs on the same new workspace; a previous run crashed holding the lease; CI retried a job while the first was still running; a stale lease left by a terminated process.
Related errors
- state blob is already locked
- Error unlocking Azure state. Lock ID: %s Error: %s You may
- blob metadata %q was empty
- failed to retrieve lock info: %s
- lock id %q does not match existing lock
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/e05ee4e97ff44011.
Report an issue: GitHub.