Terraform "Error acquiring the state lock"? Don't reflexively force-unlock
Your pipeline fails with Error acquiring the state lock: ConditionalCheckFailedException. The fastest-looking fix — terraform force-unlock or -lock=false — is also the one that can corrupt your state and orphan real infrastructure.
What the error means
Terraform takes a state lock before writing, so two runs can't modify state at once (which would corrupt it). The lock lives in the backend — a DynamoDB item for S3, a .tflock for GCS, a blob lease for Azure, a side-channel for Terraform Cloud. ConditionalCheckFailedException means the backend rejected your lock acquisition because a lock already exists. Someone — or something — holds it.
The trap: most of the time it's a stale lock from a crashed run or a killed CI job, so force-unlocking works. But you cannot tell a stale lock from a live apply by the error code alone — and force-unlocking a live apply lets two runs write state concurrently, which is exactly how state gets corrupted. The error code doesn't tell you which situation you're in.
The safe fix: read the Lock Info first
- Read the Lock Info block in the error —
Who(who holds it),Created(how old),Operation. IfCreatedis recent and you recognizeWho, someone is actively running Terraform. Wait for them to finish — don't break their lock. - Only if it's genuinely stale (a crashed process, a dead CI runner, no live run): back up the state file, then
terraform force-unlock <LockID>using the ID from the error. - If force-unlock fails (malformed lock, backend unreachable): delete the backend lock directly — DynamoDB
delete-itemon the LockID,gsutil rmthe.tflock, oraz storage blob lease break— but only after confirming no live apply.
Two things not to do
- Don't use
-lock=falseas a habit — it disables locking so two runs can corrupt state. Only if you're certain you're the sole runner. - Watch parallel
planjobs — Terraform locks even duringplan, so concurrent CI plan jobs cause false lock contention. Serialize them or use separate workspaces.
Snapback's iac-state family catches both the lock error and state drift — pass the error to diagnose_infra_error and it returns the check-Who/Created-before-force-unlock fix, so an agent doesn't blindly break a live lock.
Machine-readable guide: https://snapback.sh/llms.txt · Tool discovery: https://snapback.sh/.well-known/mcp.json · MCP endpoint: https://api.snapback.sh/mcp. Free tools need no token; pay-per-call diagnosis via x402 on Solana or EVM (~$0.0032 USDC).