This error occurs when Terraform cannot acquire a lock on your state file, typically due to a previous incomplete operation or concurrent access. It happens most often with S3 backends using DynamoDB for state locking.
Terraform uses state locking to prevent multiple processes from modifying the state file simultaneously, which could cause corruption. The ConditionalCheckFailedException error indicates that the conditional check for acquiring a lock failed—usually because another process already holds the lock or a previous operation was interrupted before releasing it. This is commonly seen when using S3 backends with DynamoDB for state management, where Terraform attempts to write a new lock record under the condition that one doesn't already exist.
Before forcing an unlock, confirm that no Terraform operations are currently in progress. Check for hanging processes:
On Linux/Mac:
ps aux | grep terraformOn Windows (PowerShell):
Get-Process terraform* -ErrorAction SilentlyContinueIf you find active processes, allow them to complete naturally. If they're hung, kill them only after confirming no one else is using Terraform:
kill -9 <process_id>Terraform provides the Lock ID in the error message. Use this to force-unlock the state:
terraform force-unlock <LOCK_ID>Example:
terraform force-unlock 49b6e22e-1234-5678-90ab-3e3097cf95d4WARNING: Only force-unlock if you are absolutely certain no other process holds the lock. Forcing an unlock while another process is writing state will corrupt it.
If you receive a permission error, verify your AWS IAM user has the required permissions for DynamoDB lock management:
{
"Effect": "Allow",
"Action": [
"dynamodb:DescribeTable",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:DeleteItem"
],
"Resource": "arn:aws:dynamodb:*:*:table/terraform-locks"
}Also ensure you have the correct S3 permissions for your state file:
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::your-bucket/path/terraform.tfstate*"
}If terraform force-unlock doesn't work, you can manually remove the lock from DynamoDB using the AWS CLI:
List current locks:
aws dynamodb scan --table-name terraform-locks --region us-east-1Delete a specific lock:
aws dynamodb delete-item \
--table-name terraform-locks \
--key '{"LockID": {"S": "your-bucket/path/terraform.tfstate"}}' \
--region us-east-1Replace terraform-locks with your actual DynamoDB table name and update the S3 path accordingly.
After releasing the lock, retry your Terraform operation:
terraform plan
terraform applyOptionally, use a lock timeout to prevent this issue from repeating:
terraform plan -lock-timeout=10m
terraform apply -lock-timeout=15mThis gives concurrent operations up to 10-15 minutes to complete before timing out.
S3-Native State Locking (Terraform 1.11+): Starting with Terraform 1.11.0, S3-native state locking is generally available as a replacement for DynamoDB-based locking. If you're experiencing frequent lock issues with DynamoDB, consider migrating to S3-native locking by updating your backend configuration and removing the DynamoDB table. This eliminates an external dependency and simplifies lock management.
Lock Timeout Defaults: By default, Terraform waits 10 seconds to acquire a lock before failing. Increasing the -lock-timeout value (e.g., to 30s or 1m) can help with transient network issues or slow backends.
Production Safety: In production environments, always prefer terraform force-unlock over -lock=false. The latter bypasses locking entirely and risks concurrent state modifications. Only use -lock=false for emergency reads (e.g., terraform state list -lock=false).
Preventing Future Occurrences: Implement graceful shutdown handlers in CI/CD pipelines to ensure Terraform releases locks properly. Avoid using kill -9 for Terraform processes; instead, use SIGTERM to allow cleanup. Set reasonable timeouts in your CI/CD configuration (e.g., 30 minutes for apply operations) to catch hung processes early.
Error: Error installing helm release: cannot re-use a name that is still in use
How to fix "release name in use" error in Terraform with Helm
Error: Error creating GKE Cluster: BadRequest
BadRequest error creating GKE cluster in Terraform
Error: External program failed to produce valid JSON
External program failed to produce valid JSON
Error: Unsupported argument in child module call
How to fix "Unsupported argument in child module call" in Terraform
Error: network is unreachable
How to fix "network is unreachable" in Terraform