TerraformPilot

DevOps

Fix Terraform Error: Error Acquiring the State Lock Timeout Exceeded

Fix terraform state lock timeout exceeded. Force unlock stuck locks, increase timeout, prevent parallel runs in CI/CD

LLuca Berton2 min read

Quick Answer

#
# Check if another terraform process is running
ps aux | grep terraform
 
# If no process is running, force unlock
terraform force-unlock LOCK_ID

The Error

#
Error: Error acquiring the state lock
 
Error message: ConditionalCheckFailedException: The conditional request failed
Lock Info:
  ID:        a1b2c3d4-e5f6-7890-abcd-ef1234567890
  Path:      my-bucket/prod/terraform.tfstate
  Operation: OperationTypeApply
  Who:       user@machine
  Version:   1.9.0
  Created:   2026-04-12 10:30:00.000000000 +0000 UTC
 
Terraform acquires a state lock to protect against two processes
writing to the state at the same time. The lock was not released
within the configured timeout period.

What Causes This

#
  1. Another terraform process is running — someone else on the team is applying
  2. Previous run crashed — Ctrl+C, network drop, or CI/CD runner killed mid-apply
  3. Lock timeout too short — large deployments take longer than the default timeout
  4. CI/CD running parallel jobs — multiple pipelines targeting the same state

Solution 1: Wait and Retry

#

The most common case — someone else is running terraform. Wait for them to finish:

# Check who holds the lock (shown in error message)
# Who: user@machine — ask that person
 
# Retry with a longer timeout
terraform apply -lock-timeout=10m

Solution 2: Force Unlock a Stuck Lock

#

If no terraform process is running (crashed or killed):

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

Before force-unlocking, verify no process is actually running:

# Local machine
ps aux | grep terraform
 
# CI/CD — check running pipelines in GitLab/GitHub
 
# Check DynamoDB directly (S3 backend)
aws dynamodb scan \
  --table-name terraform-locks \
  --filter-expression "LockID = :id" \
  --expression-attribute-values '{":id":{"S":"my-bucket/prod/terraform.tfstate"}}'

Solution 3: Prevent Parallel Runs in CI/CD

#

GitLab CI — use resource_group:

apply-prod:
  stage: deploy
  resource_group: terraform-prod   # Only one job at a time
  script:
    - terraform apply -auto-approve -lock-timeout=5m

GitHub Actions — use concurrency:

jobs:
  apply:
    concurrency:
      group: terraform-prod
      cancel-in-progress: false    # Don't cancel running applies!
    steps:
      - run: terraform apply -auto-approve

Solution 4: Configure Lock Timeout

#
# Default timeout is 0s (fail immediately)
# Set a reasonable timeout for team environments
terraform apply -lock-timeout=5m
terraform plan -lock-timeout=5m

Or in CI/CD:

export TF_CLI_ARGS_apply="-lock-timeout=5m"
export TF_CLI_ARGS_plan="-lock-timeout=5m"

How State Locking Works

#
BackendLock Mechanism
S3DynamoDB table
GCSNative object locking
Azure BlobBlob lease
Terraform CloudBuilt-in
ConsulKV lock
Local.terraform.tfstate.lock.info file

S3 + DynamoDB Setup

#
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"   # This enables locking
    encrypt        = true
  }
}
 
# Create the lock table
resource "aws_dynamodb_table" "terraform_locks" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"
 
  attribute {
    name = "LockID"
    type = "S"
  }
}

Troubleshooting Checklist

#
  1. Is another terraform process actually running? → Wait or coordinate
  2. Did a CI/CD runner crash? → Check pipeline status, then force-unlock
  3. Using S3 backend without DynamoDB table? → Add dynamodb_table config
  4. Multiple workspaces on same lock table? → That's fine, locks are per-state-file
  5. Still failing after force-unlock? → Check IAM permissions on DynamoDB table

Hands-On Courses

#

Conclusion

#

State lock errors mean another terraform process holds the lock or a previous run crashed. Check for running processes first. If the lock is stale, use terraform force-unlock LOCK_ID. Prevent the issue with CI/CD resource_group or concurrency controls and set -lock-timeout=5m in team environments.

#Terraform#Troubleshooting#DevOps#Error Fix#Infrastructure as Code

Share this article