Terraform uses state to track the infrastructure it manages. When you run a plan or apply operation, Terraform compares the configuration with the recorded state and the actual resources to determine what needs to change.
If two operations modify the same state at the same time, they can interfere with each other. To reduce this risk, Terraform supports state locking with backends that implement the feature.
Sometimes, however, a Terraform command waits for a lock that another operation holds. A previous run may have crashed, a CI/CD job may still be active, or a lock may remain after an interrupted operation.
Removing the lock without understanding the situation can create bigger problems, including conflicting infrastructure changes and inconsistent state.
In this article, we will look at why Terraform state locking gets stuck, how to investigate the cause, and how to recover safely.
What Is Terraform State Locking?
Terraform state records the relationship between resources in your configuration and the infrastructure Terraform manages.
For example, a configuration might define an Azure virtual machine, an AWS security group, or a Kubernetes resource. Terraform uses the state to track those managed resources across operations.
When a backend supports state locking, Terraform can acquire a lock before performing an operation that might write state. The lock helps prevent multiple operations from modifying the same state simultaneously.
Consider two engineers working on the same environment:
Engineer A starts terraform apply.
Engineer B starts another terraform apply against the same state.
Terraform detects that the state is already locked.
Engineer B must wait or stop until the lock can be acquired.
This behavior protects the state from concurrent modifications. A lock is not necessarily an error; it may indicate that another operation is still working.
Why Does a Terraform Lock Get Stuck?
Several situations can leave an operation waiting for a lock or make it appear that a lock is no longer valid.
A previous Terraform process is still running.
A CI/CD pipeline is waiting for approval or has stalled.
A terminal closed while the operation was in progress.
A machine or runner crashed during an operation.
A network interruption affected communication with the backend.
A previous operation terminated unexpectedly and left a lock record that needs investigation.
The exact locking behavior depends on the backend. For example, an S3 backend using native S3 lock files behaves differently from an older configuration that uses a DynamoDB lock table.
Before attempting recovery, identify the backend and determine whether the operation that acquired the lock is still active.
Step 1: Read the Lock Error Carefully
When Terraform cannot acquire a lock, it usually reports that the state is locked and provides information about the lock.
The message may include fields such as:
The lock ID is especially important if you eventually need to force-unlock the state.
For example, the error may resemble this:
Error acquiring the state lock
Error message: state is locked
Lock Info:
ID: 12345678-abcd-1234-abcd-123456789012
Operation: OperationTypeApply
Who: runner@build-agent
Version: 1.x
Created: 2026-10-22 08:30:00 UTC
Path: example/environment/terraform.tfstate
This is an illustrative example, not a real lock record. Use the actual details from your Terraform output.
Do not assume that a lock is stale simply because its creation time is old. A long-running deployment, a manual approval step, or a slow provider operation may still be active.
Step 2: Check Whether Another Terraform Operation Is Running
Before changing the lock, investigate whether another operation is still working.
Check the relevant systems:
Look for active Terraform processes on the machine or runner.
Inspect CI/CD jobs that deploy the same environment.
Check whether another engineer is running Terraform locally.
Review deployment logs to see whether the previous operation completed or failed.
Confirm which backend, workspace, and state are involved.
If a deployment is still running, allow it to finish or coordinate a controlled cancellation through the system that started it.
Avoid starting another apply operation against the same state while the first operation may still be changing infrastructure.
This is especially important in shared environments where several pipelines or engineers can target the same state.
Step 3: Confirm the Backend and Workspace
A Terraform configuration can use different backends for different environments. Each backend has its own locking and recovery behavior.
Check the backend configuration and the workspace selected by the current Terraform directory.
terraform workspace show
terraform workspace list
These commands help you identify the current workspace and the available workspaces.
Also review the backend configuration in your Terraform project. Do not assume that the default workspace or a familiar state path is the one involved in the error.
If the backend configuration has changed, initialize Terraform as appropriate for that configuration:
terraform init
Review any prompts carefully. Do not migrate or reconfigure state simply to get past a lock error unless the change is intentional and you understand its impact.
Step 4: Use the Lock Timeout When Waiting Is Appropriate
If another operation is expected to finish shortly, Terraform can wait for a lock instead of failing immediately.
Use the lock timeout option:
terraform plan -lock-timeout=5m
For an apply operation:
terraform apply -lock-timeout=5m
The timeout tells Terraform how long to keep trying to acquire the lock. It does not remove a lock or resolve a genuinely abandoned operation.
Use a timeout that makes sense for your workflow. A longer timeout can be helpful in CI/CD pipelines where concurrent operations are expected, but it should not hide a deployment that is stuck indefinitely.
If the lock cannot be acquired after the timeout, investigate the owner and the backend rather than repeatedly increasing the waiting period.
Step 5: Understand When Force-Unlock Is Appropriate
Terraform provides a force-unlock command for removing a lock when you have confirmed that it belongs to an operation that is no longer running.
The command requires the lock ID reported by Terraform:
terraform force-unlock 12345678-abcd-1234-abcd-123456789012
Replace the example ID with the actual lock ID.
Terraform may ask you to confirm the action. Verify that you are operating in the correct directory, workspace, and backend before proceeding.
Force-unlock should be used only when you are confident that the lock is stale and the operation that acquired it has stopped.
Removing a valid lock can allow another Terraform process to modify the same state while the original operation is still running. That can lead to conflicting changes or state problems.
For that reason, do not use force-unlock as a routine response to every locking error.
Step 6: Check the State Before Running Apply Again
After a confirmed stale lock has been removed, do not immediately assume that the previous deployment made no changes.
An interrupted apply may have created some resources, updated others, or completed infrastructure changes without finishing all state updates.
Start by checking the configuration and current state.
terraform state list
This command lists the resources currently tracked in the selected state.
Next, review the proposed changes:
terraform plan
Inspect the plan carefully before applying it. Terraform may propose additional changes because the interrupted operation did not complete, because the real infrastructure differs from the state, or because the configuration has changed.
If the plan shows unexpected resource replacement or deletion, stop and investigate before proceeding.
Avoid editing the state file manually or removing resources from state simply to silence an error. State operations should be deliberate and based on a clear understanding of the resource and backend.
Step 7: Check for Infrastructure Changes That Were Partially Applied
Terraform operations interact with external providers. A provider operation can succeed even if the Terraform process later fails.
For example, an apply might create a virtual machine successfully but fail while updating another resource. The state and actual infrastructure may then require reconciliation.
Review the provider's resource status and the relevant deployment logs. Then run a fresh Terraform plan to compare the declared configuration, recorded state, and infrastructure.
The refresh behavior of Terraform depends on the command and version, so use the normal planning workflow for your installed version and inspect any refresh-related options before changing them.
Do not automatically rerun an apply if the previous operation stopped in the middle of a destructive change. Confirm that the proposed actions are correct first.
Step 8: Prevent Locking Problems in CI/CD Pipelines
Many state-locking incidents happen when multiple pipelines attempt to deploy the same environment.
For example, a feature branch pipeline may start an apply while the main branch pipeline is already deploying to the same state.
Several practices can reduce these conflicts:
Serialize deployment jobs that target the same state.
Use separate states for environments that need independent deployment lifecycles.
Avoid running manual applies while a pipeline is deploying.
Configure appropriate lock timeouts for expected contention.
Make pipeline cancellation behavior explicit.
Keep Terraform and provider versions consistent across deployment agents.
Record the environment, workspace, and pipeline run ID in deployment logs.
Separate state files should reflect real infrastructure ownership boundaries. Splitting state without considering dependencies can introduce other operational problems.
Common Mistakes to Avoid
Force-unlocking without checking the owner
A lock may belong to an active pipeline or an engineer's local operation. Removing it too early can allow concurrent state changes.
Assuming an old lock is stale
The age of the lock is only one clue. Check process status, pipeline logs, and backend activity before deciding.
Repeatedly retrying apply
Repeated retries do not resolve a lock conflict and may make troubleshooting harder. Identify the operation that owns the lock first.
Ignoring the current workspace
A command run against the wrong workspace or backend can affect a different environment than intended. Verify the target before performing state operations.
Assuming an interrupted apply changed nothing
Some infrastructure changes may have succeeded before the process failed. Review the state and actual resources before applying again.
Manually deleting backend lock records
Backend lock mechanisms are implementation-specific. Manually deleting lock records or lock files can bypass coordination and is not a safe substitute for the supported recovery procedure.
Best Practices for Production Environments
Treat state locking as a safety mechanism, not an obstacle to bypass.
Identify the lock owner and active operation before recovery.
Confirm the correct backend and workspace.
Use lock timeouts for expected contention.
Reserve force-unlock for confirmed stale locks.
Review the Terraform plan after an interrupted operation.
Check actual infrastructure when an apply may have partially succeeded.
Serialize CI/CD operations that target the same state.
Keep deployment logs detailed enough to identify the operation, environment, and responsible runner.
Back up important state and follow the backend's documented recovery procedures.
Summary
Terraform state locking prevents concurrent operations from modifying the same state at the same time. A lock that appears stuck may belong to an active deployment, or it may be left behind after a process failure.
Start by inspecting the lock details, checking active processes and pipelines, and confirming the backend and workspace. Use a lock timeout when waiting is reasonable, and use force-unlock only after confirming that the original operation has stopped.
After recovering the lock, review the state and run a fresh plan before applying changes. This helps ensure that a locking problem does not turn into an infrastructure or state-recovery incident.
Join the conversation! Your thoughts help the community grow.