Terraform state lock errors occur when Terraform cannot acquire an exclusive lock on your state file, usually due to concurrent operations, stale locks, or hung processes. This error prevents infrastructure changes and requires identifying and releasing the conflicting lock.
Terraform uses a pessimistic concurrency model that acquires an exclusive lock on the entire state file whenever an operation (plan, apply, or destroy) touches state. This global mutex ensures two processes never write to state simultaneously. When Terraform cannot acquire this lock—because another operation already holds it, the lock is stale, or permissions are insufficient—you get this error. The lock can be held by a hung process, a concurrent execution in CI/CD, network interruption aftermath, or permission restrictions in remote backends like Terraform Cloud.
First, determine if another Terraform operation is legitimately in progress. Check with your team to see if someone is actively running terraform apply or plan. If you are the only one working, the lock is likely stale.
Check for hung Terraform processes on your machine:
ps aux | grep terraformIf you find a hung process, note its PID for potential termination. In a team environment, coordinate with others before forcing a lock release.
The error message contains a lock ID. Use terraform force-unlock to release it:
terraform force-unlock LOCK_IDFor example:
terraform force-unlock 6ff0f1f7-c0ac-4e61-8265-7d2bcce2b4eaTo skip the confirmation prompt:
terraform force-unlock -force LOCK_IDThis removes the lock from your backend storage (S3, Azure, Consul, etc.) allowing new operations to proceed.
If you identified a hung terraform process in step 1, terminate it:
kill -9 PIDFor example:
kill -9 12345On Windows, use:
Get-Process terraform | Stop-Process -ForceThis prevents the process from continuing in the background and ensures the lock is truly abandoned.
If using Terraform Cloud, AWS S3, Azure, or Consul, verify your authentication has proper permissions:
For Terraform Cloud:
terraform loginEnsure the authenticated user belongs to:
- The owners team, OR
- Teams with "Manage all workspaces" permissions, OR
- Teams with "Project Admin" permissions for the specific project
For AWS S3/DynamoDB:
aws sts get-caller-identityVerify the returned user/role has s3:GetObject, s3:PutObject, and dynamodb:PutItem permissions on your backend resources.
For Azure Blob Storage:
Verify your storage account credentials and container access permissions are correct.
If terraform force-unlock doesn't work with S3 backends, delete the lock directly from DynamoDB:
aws dynamodb delete-item \
--table-name terraform-state-lock \
--key '{"LockID": {"S": "your-bucket/path/terraform.tfstate"}}' \
--region us-east-1Replace "your-bucket/path/terraform.tfstate" with your actual state path. This removes the stale lock entry from the DynamoDB lock table, allowing new lock acquisitions.
For Azure Blob Storage, locate and delete the .tflock file in your storage container:
az storage blob delete \
--account-name myaccount \
--container-name mycontainer \
--name path/to/terraform.tfstate.tflockPrevent future state lock errors by using lock timeouts:
terraform apply -lock-timeout=10mOr in CI/CD pipelines:
terraform init -lock=true -lock-timeout=120sFor CI/CD systems, implement mutex locks:
In GitHub Actions:
concurrency:
group: terraform-state
cancel-in-progress: falseIn GitLab CI:
resource_group: terraform_stateIn Azure DevOps or Jenkins, ensure only one pipeline job can run terraform against the same state file at a time. This prevents concurrent operations from even attempting simultaneous locking.
State locking is not a bug—it's Terraform's safety mechanism. The "Error acquiring the state lock" means Terraform is working as designed: preventing concurrent writes to infrastructure state.
Lock timeouts in CI/CD: The -lock-timeout parameter tells Terraform to retry lock acquisition for the specified duration. Set it to 10-15 minutes in pipelines to handle brief network hiccups and allow other operations to complete naturally.
DynamoDB TTL: If using S3 backends, enable DynamoDB TTL on your lock table to automatically expire locks older than a threshold (e.g., 1 hour). This prevents truly orphaned locks from blocking operations forever.
Emergency bypass (last resort): terraform apply -lock=false bypasses locking entirely. Only use when absolutely certain no other operations are in progress. This is dangerous and can lead to corrupted state if multiple writes occur simultaneously.
Local state files: For local development, remove .terraform.tfstate.lock.info manually if a process crashed, but never do this in team/production environments without coordination.
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