Fix: Terraform Error locking state: Error acquiring the state lock
Quick Answer
How to fix Terraform state lock error caused by concurrent runs, crashed operations, DynamoDB lock table issues, and stale lock IDs.
The Error
You run terraform plan or terraform apply and get:
Error: Error locking state: Error acquiring the state lock
Error message: ConditionalCheckFailedException: The conditional request failed
Lock Info:
ID: abcd1234-ef56-7890-abcd-ef1234567890
Path: my-project/terraform.tfstate
Operation: OperationTypeApply
Who: user@hostname
Version: 1.7.0
Created: 2024-01-15 10:30:00.000000000 +0000 UTC
Info:
Terraform acquires a state lock to protect against two processes writing
to the state at the same time. This error means Terraform could not
acquire the lock.Terraform cannot acquire the state lock because another process is already holding it. The lock prevents concurrent state modifications that could corrupt the state file.
Why This Happens
Terraform uses state locking to ensure only one person or process modifies infrastructure at a time. When using a remote backend (S3 + DynamoDB, Terraform Cloud, GCS, etc.), a lock entry is created before any state-modifying operation.
Common causes:
- Another
terraform applyis running. A teammate or CI/CD pipeline is actively applying changes. - Previous operation crashed. A
terraform applywas interrupted (Ctrl+C, network failure, timeout) and the lock was not released. - CI/CD pipeline timeout. A pipeline ran
terraform applybut timed out before completion, leaving the lock. - DynamoDB table issue. The lock table does not exist, has wrong permissions, or the lock entry is stale.
- Terraform Cloud workspace locked. Someone locked the workspace manually or a run is queued.
Fix 1: Wait for the Other Operation
Check if another operation is genuinely running. The error shows Who: (the user) and Created: (when the lock was acquired).
If the lock was created minutes ago by a teammate, wait for their operation to finish:
# Check with your team
# Or look at CI/CD pipeline statusIf the lock is recent and the Who: field shows a valid user or CI system, do not force-unlock — wait for the operation to complete.
Fix 2: Force Unlock a Stale Lock
If the lock is stale (the operation crashed, the CI pipeline timed out, or the user confirmed they are not running anything):
terraform force-unlock LOCK_IDUse the Lock ID from the error message:
terraform force-unlock abcd1234-ef56-7890-abcd-ef1234567890Terraform asks 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 to confirm.Type yes to confirm.
Warning: Only force-unlock if you are certain no other operation is running. Force-unlocking while another process is actively modifying state can corrupt the state file.
Pro Tip: Before force-unlocking, check if the user listed in
Who:is still running Terraform. Ask them directly. If the lock was created by a CI/CD system, check the pipeline status. A stale lock from a crashed pipeline is safe to force-unlock; a lock from an in-progress pipeline is not.
Fix 3: Fix DynamoDB Lock Table (AWS S3 Backend)
For S3 backends, the lock is stored in a DynamoDB table. If the table does not exist or is misconfigured:
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"
}
}Backend configuration:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "project/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}Check the table exists and has the right schema:
aws dynamodb describe-table --table-name terraform-locksThe table must have a string hash key named LockID.
Check DynamoDB permissions:
Your IAM user or role needs dynamodb:GetItem, dynamodb:PutItem, dynamodb:DeleteItem on the lock table:
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:DeleteItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/terraform-locks"
}For IAM permission issues in general, see Fix: AWS AccessDeniedException.
Fix 4: Manually Remove a Stale DynamoDB Lock
If terraform force-unlock does not work, remove the lock entry directly from DynamoDB:
aws dynamodb delete-item \
--table-name terraform-locks \
--key '{"LockID": {"S": "my-project/terraform.tfstate"}}'Or use the DynamoDB console:
- Go to DynamoDB → Tables → terraform-locks → Explore table items
- Find the item with
LockIDmatching your state file path - Delete the item
Then retry your Terraform command.
Warning: Directly deleting DynamoDB items bypasses Terraform’s safety checks. Only do this when terraform force-unlock fails.
Fix 5: Fix Terraform Cloud Locks
If using Terraform Cloud or Terraform Enterprise:
Check the workspace:
- Go to Terraform Cloud → Workspaces → Your workspace
- Check for running or queued plans/applies
- If a run is stuck, click “Discard run”
Unlock the workspace:
- Go to Workspace → Settings → General
- Click “Force Unlock” (requires admin permissions)
Via API:
curl -s \
--header "Authorization: Bearer $TFC_TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
"https://app.terraform.io/api/v2/workspaces/$WORKSPACE_ID/actions/force-unlock"Common Mistake: Running
terraform applylocally when the workspace is configured for remote execution. The local run acquires a lock that conflicts with the remote execution. Useterraform cloudfor remote execution or configureexecution_mode = "local"in the workspace settings.
Fix 6: Prevent Lock Issues in CI/CD
Configure your CI/CD pipeline to handle locks gracefully:
GitHub Actions:
jobs:
terraform:
runs-on: ubuntu-latest
concurrency:
group: terraform-${{ github.ref }}
cancel-in-progress: false # Don't cancel — let it finish
steps:
- uses: hashicorp/setup-terraform@v3
- run: terraform init
- run: terraform apply -auto-approve
timeout-minutes: 30concurrency ensures only one Terraform job runs at a time per branch.
Add timeouts:
- run: terraform apply -auto-approve
timeout-minutes: 30This kills the job after 30 minutes, but the lock might still be held. Add cleanup:
- run: terraform apply -auto-approve
timeout-minutes: 30
continue-on-error: true
- run: terraform force-unlock -force $LOCK_ID || true
if: failure()Use -lock-timeout:
terraform apply -lock-timeout=5mThis waits up to 5 minutes for the lock to become available before failing. Useful when multiple pipelines might run close together.
Fix 7: Fix State File Corruption
If the state file is corrupted (maybe from a force-unlock during an active write), restore from backup:
S3 versioning:
# List state file versions
aws s3api list-object-versions --bucket my-terraform-state --prefix project/terraform.tfstate
# Restore a previous version
aws s3api get-object --bucket my-terraform-state --key project/terraform.tfstate --version-id VERSION_ID terraform.tfstate.backupPull the current state:
terraform state pull > current-state.jsonCheck if the state is valid JSON. If not, restore from the backup.
Push a fixed state:
terraform state push terraform.tfstate.backupFor the general state lock error article, see Fix: Terraform error acquiring state lock.
Fix 8: Use State Lock Alternatives
Disable locking (not recommended):
terraform apply -lock=falseThis bypasses locking entirely. Only use this as a last resort for debugging. Running without locks in a team environment can corrupt the state file.
Use local state (for solo development):
terraform {
backend "local" {
path = "terraform.tfstate"
}
}Local backends still use file-system locks but do not have DynamoDB or network-related lock issues.
Still Not Working?
Check for network issues. If Terraform cannot reach DynamoDB or Terraform Cloud, it cannot acquire or release locks. Check your network connectivity and VPN status.
Check for AWS region mismatch. The DynamoDB table must be in the same region specified in the backend configuration. A mismatch causes lock acquisition failures.
Check for IAM session expiration. If your AWS session token expired during a long terraform apply, the lock release fails. Use longer session durations for Terraform operations.
Check for S3 bucket access. If Terraform cannot read/write the state file in S3, it fails before attempting the lock:
aws s3 ls s3://my-terraform-state/project/For Terraform provider installation failures, see Fix: Terraform failed to install provider.
Consider using OpenTofu if you need open-source Terraform. OpenTofu is a fork that uses the same state format and locking mechanisms.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Terraform Failed to install provider (or Failed to query available provider packages)
How to fix 'Failed to install provider' and 'Failed to query available provider packages' errors in Terraform, covering registry issues, version constraints, network problems, platform support, and air-gapped environments.
Fix: Error Acquiring the State Lock (Terraform)
How to fix 'Error acquiring the state lock', 'Error locking state', 'Failed to load backend', and other common Terraform state and backend errors. Covers force-unlock, DynamoDB lock tables, S3 backend issues, state file corruption, and provider version conflicts.
Fix: AWS CloudFormation stack in ROLLBACK_COMPLETE or CREATE_FAILED state
How to fix AWS CloudFormation ROLLBACK_COMPLETE and CREATE_FAILED errors caused by IAM permissions, resource limits, invalid parameters, and dependency failures.
Fix: AWS AccessDeniedException when calling an AWS service operation
How to fix AWS AccessDeniedException caused by missing IAM permissions, explicit denies, SCPs, resource policies, permission boundaries, and misconfigured roles.