Terraform IaC DynamoDB

Terraform state lock stuck: Error acquiring the state lock

Fix a stuck Terraform state lock when terraform plan or apply fails with Error acquiring the state lock after a crashed or timed-out operation.

·
Terraform refuses to run plan or apply: "Error acquiring the state lock". No infrastructure changes can proceed until the lock is released. This runbook shows how to safely verify and remove the stuck lock.

This runbook covers Terraform state lock issues common in team environments with remote backends. For broader infrastructure management guidance, see Cloud Under Control or book a consulting session.

Symptoms

terraform plan or terraform apply fails immediately with a lock error:

# Terraform refuses to acquire state lock
terraform plan

# Error: Error acquiring the state lock
#
# Error message: ConditionalCheckFailedException: The conditional request failed
# Lock Info:
#   ID:        a1b2c3d4-e5f6-7890-abcd-ef1234567890
#   Path:      my-project/terraform.tfstate
#   Operation: OperationTypeApply
#   Who:       user@hostname
#   Version:   1.5.7
#   Created:   2026-06-20 14:32:01.123456 +0000 UTC
#   Info:
#
# Terraform acquires a state lock to protect the state from being
# written by multiple users at the same time.

The lock persists indefinitely. All plan, apply, and destroy commands fail for the entire team. CI/CD pipelines using this state file are also blocked.

Cause

Terraform uses a locking mechanism to prevent concurrent state modifications. With AWS backends, this lock is stored in a DynamoDB table. A lock becomes stuck when:

  • A terraform apply was interrupted (Ctrl+C, network timeout, CI/CD runner killed)
  • The CI/CD pipeline timed out or was cancelled mid-operation
  • The operator’s machine crashed during a long-running apply
  • A network partition occurred between the client and DynamoDB

The lock entry remains in DynamoDB because the process that created it never completed the unlock step. Terraform has no built-in TTL for locks, so it persists until manually removed.

Fix

A) Verify no operation is actually running:

Before force-unlocking, confirm that no legitimate Terraform process holds the lock:

# Check the lock info for details about who holds it
terraform plan 2>&1 | grep -A 10 "Lock Info"

# Check if any CI/CD pipeline is currently running Terraform
# (GitHub Actions example)
gh run list --workflow=terraform.yml --status=in_progress

# Check DynamoDB lock table directly
aws dynamodb get-item \
  --table-name terraform-state-locks \
  --key '{"LockID": {"S": "my-project/terraform.tfstate"}}' \
  --query 'Item.Info.S' --output text

B) Force-unlock the state (after confirming no active operation):

# Use the Lock ID from the error message
terraform force-unlock a1b2c3d4-e5f6-7890-abcd-ef1234567890

# Terraform will ask for confirmation:
# Do you really want to force-unlock?
# Terraform will remove the lock on the remote state.
# This will allow local Terraform commands to modify this state,
# even though it may still be in use. Only 'yes' will be accepted.
#
# Enter a value: yes

C) Remove the lock directly from DynamoDB (if force-unlock fails):

# If terraform force-unlock itself fails, remove the DynamoDB item directly
aws dynamodb delete-item \
  --table-name terraform-state-locks \
  --key '{"LockID": {"S": "my-project/terraform.tfstate"}}'

# Verify the lock is gone
aws dynamodb get-item \
  --table-name terraform-state-locks \
  --key '{"LockID": {"S": "my-project/terraform.tfstate"}}'
# Expected: empty response (no Item)

Prevention: Configure CI/CD timeouts to always exceed expected Terraform run duration. Add a cleanup step in your pipeline that runs terraform force-unlock on failure. Consider wrapping Terraform in a script that catches SIGTERM and attempts a graceful unlock before exit.

Verification

# 1. Confirm terraform plan runs without lock errors
terraform plan
# Expected: normal plan output, no lock error

# 2. Verify state is consistent (no corruption from interrupted apply)
terraform plan -detailed-exitcode
# Exit code 0 = no changes needed (state is consistent)
# Exit code 2 = changes detected (review them before applying)

# 3. Check DynamoDB lock table is clean
aws dynamodb get-item \
  --table-name terraform-state-locks \
  --key '{"LockID": {"S": "my-project/terraform.tfstate"}}'
# Expected: empty response

# 4. Run a CI/CD pipeline to confirm it works end-to-end
# (trigger a no-op plan in your pipeline)

If terraform plan completes without the lock error, the issue is resolved. If the plan shows unexpected changes, the interrupted apply may have partially modified infrastructure. Review the diff carefully before applying.

A locked Terraform state blocks all infrastructure changes: zero deployments, zero scaling adjustments, zero security patches. For teams without IaC expertise, a stuck lock can mean hours of downtime while someone figures out how to safely release it. Every minute the lock persists, the risk of a manual workaround (editing state, bypassing pipelines) increases.

 

Jerzy Kopaczewski

Terraform blocking your deployments?

Book a free 30-minute call. We'll review your IaC setup and help you prevent state lock issues for good.