Skip to content
Latchkey

Terraform "Error acquiring the state lock: ConditionalCheckFailedException" in CI

The S3 backend writes a lock item to DynamoDB before touching state. ConditionalCheckFailedException means that item already exists, so another apply holds the lock or a previous run died without releasing it. Terraform refuses to proceed.

What this error means

plan or apply stops with "Error acquiring the state lock" and a DynamoDB ConditionalCheckFailedException, printing the Lock Info: ID, Who, Created, and the lock path.

Terraform
Error: Error acquiring the state lock

Error message: operation error DynamoDB: PutItem, ConditionalCheckFailedException:
The conditional request failed
Lock Info:
  ID:        9b2c1a44-7f0e-4d8a-...
  Path:      my-tf-state/env/prod/terraform.tfstate
  Operation: OperationTypeApply
  Who:       runner@fv-az123

Common causes

Another run currently holds the lock

Two pipelines (or a manual run and CI) target the same state at once. The first wrote the DynamoDB lock item; the second cannot create it, so the conditional put fails.

A crashed run left a stale lock item behind

A cancelled job or a killed runner never ran the release, so the lock item persists in DynamoDB and blocks every later run.

How to fix it

Wait for the holder, then force-unlock if it is dead

  1. Confirm from the Lock Info Who/Created that no live run still holds it.
  2. If the holder crashed, release the lock with the exact ID from the error.
  3. Re-run plan or apply once the lock is gone.
Terminal
terraform force-unlock 9b2c1a44-7f0e-4d8a-...

Serialize state-mutating jobs

Use a concurrency group so only one apply touches a given state at a time, which prevents the lock contention rather than recovering from it.

.github/workflows/ci.yml
concurrency:
  group: terraform-${{ github.ref }}
  cancel-in-progress: false

How to prevent it

  • Run apply behind a concurrency group keyed to the workspace or branch.
  • Add a cleanup step or trap so cancelled jobs release the lock.
  • Use distinct state keys per environment so unrelated runs never contend.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →