Skip to content
Latchkey

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

The S3 backend uses a DynamoDB item as a mutex. A ConditionalCheckFailedException on lock means the item already exists -- another apply holds the lock for that state, or a previous run left it behind.

What this error means

plan/apply fails with "Error acquiring the state lock" and a DynamoDB ConditionalCheckFailedException, showing the lock ID and who holds it. It is common when two CI jobs target the same state at once.

terraform
Error: Error acquiring the state lock

Error message: operation error DynamoDB: PutItem, ConditionalCheckFailedException:
The conditional request failed
Lock Info:
  ID:        9f1c2a4e-...
  Who:       runner@ci
  Created:   2026-06-26 10:12:03

Common causes

Concurrent run holds the lock

Two pipelines (or a manual run and CI) operate on the same state simultaneously; the second cannot acquire the existing lock.

Stale lock from a killed run

A cancelled or crashed run did not release the lock, so the DynamoDB item lingers and blocks the next run.

How to fix it

Serialize runs; force-unlock only when truly stale

Ensure one run per state at a time. If a lock is confirmed orphaned, force-unlock with its ID.

Terminal
# only after confirming no run is active:
terraform force-unlock 9f1c2a4e-...

Prevent concurrent state access

  1. Use CI concurrency groups so only one job per state/workspace runs at a time.
  2. Set -lock-timeout so a run waits briefly instead of failing instantly.
  3. Identify stale locks by the Who/Created fields before unlocking.

How to prevent it

  • Serialize Terraform runs per state with CI concurrency controls.
  • Use -lock-timeout to ride out brief contention.
  • Force-unlock only after confirming the lock is orphaned.

Related guides

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