Recover safely from Terraform Error acquiring the state lock
Terraform Error acquiring the state lock means the configured backend refused a potentially state-writing operation because another lock exists or the lock service is unavailable. The safe response is to identify the exact backend, workspace, lock owner, and active run before considering force-unlock.
Prove whether a lock is active or stale, preserve sanitized state and lock evidence, let a legitimate operation finish or cancel it through its owner, use the exact lock ID only when stale status is confirmed, and verify state lineage, serial, and a new locked plan afterward.
- Terraform CLI 1.7.x, 1.8.x, 1.9.x, 1.10.x and current supported releases
- State backends HCP Terraform, S3, AzureRM, GCS, Consul, remote backends with locking
- Execution local CLI, CI runners, remote runs
- Backend and workspace identity Know the root module directory, initialized backend, selected workspace, and remote state key or workspace name. The same lock ID can be meaningless in another configuration.
terraform workspace show && terraform version - Run coordination access Be able to inspect CI pipelines, HCP Terraform runs, scheduler jobs, and operator sessions that can write the same state.
Confirm the team channel and run console used to coordinate Terraform operations. - Read access to state and logs Use credentials that can read the intended backend and operation history without widening permissions or exposing state.
terraform state pull can be attempted only after confirming the exact backend and workspace. - Protected evidence location Terraform state can contain secrets. Prepare an encrypted, access-controlled incident location outside source control before saving a snapshot.
Confirm the evidence directory is excluded from Git and restricted to incident responders. - Recovery authority Force-unlock can permit concurrent writers. Require the state owner or incident commander to approve it after active-run checks.
Record the approver, lock ID, backend, workspace, and evidence timestamp.
OneLiners never runs these steps or stores secrets. Review placeholders, versions, current state, and change-control requirements before using a command.
Full guide
What you will build
- An evidence-led response that treats state locking as protection, not an obstacle.
- A complete lock record tied to one root module, backend, workspace, state path, run, owner, and UTC timeline.
- A protected pre-recovery state snapshot with checksum plus a sanitized lineage and serial record.
- A four-way decision between active lock, routine contention, confirmed stale lock, and backend failure.
- A two-person stale-lock gate before the exact force-unlock command is allowed.
- A post-recovery proof that state identity and normal lock acquisition still work.
- An emergency containment path for mistaken unlock or possible concurrent writers.
- A prevention model based on one queue per state, bounded timeouts, visible ownership, and backend monitoring.
- Explain why Terraform Error acquiring the state lock prevents concurrent writers and protects state integrity.
- Capture and interpret Lock Info fields without using -lock=false.
- Confirm the exact initialized backend, state key, workspace, configuration revision, and Terraform version.
- Find local, CI, scheduler, and remote-platform runs that may own the lock.
- Distinguish a live lock from an orphan, short contention, or backend service failure.
- Preserve secret-bearing state safely before destructive coordination changes.
- Wait for or cancel a legitimate run through its owner and let normal cleanup release the lock.
- Use -lock-timeout for normal contention and the exact force-unlock lock ID only for a confirmed stale lock.
- Verify state lineage, serial, lock acquisition, lock release, and a reviewed plan afterward.
- Contain concurrent-writer risk without manually editing state or forcing an old snapshot.
Architecture
How the parts fit together
Terraform state locking is a distributed coordination boundary. The current configuration asks its backend to acquire a unique lock before operations that could write state. Safe recovery must connect the backend lock record to the real execution owner and preserve state identity before removing anything.
- A Terraform plan, apply, destroy, import, or state-changing operation identifies the current backend and workspace.
- The backend attempts a conditional lock and rejects the request if another valid lock already exists or coordination fails.
- Terraform prints Error acquiring the state lock and, when available, the Lock Info record.
- The responder correlates that record with local processes, CI, remote runs, schedules, and provider activity.
- An active holder completes or is cancelled through its owning platform; normal cleanup releases the lock.
- Routine contention waits through -lock-timeout while preserving locking.
- A confirmed orphan is backed by a protected state snapshot, approval, and exact lock ID.
- terraform force-unlock removes only that reviewed lock for the current configuration.
- A fresh plan proves lock acquisition and release while state lineage and serial are compared.
- If concurrent writers are possible, every writer is frozen and state/provider reconciliation replaces routine recovery.
Assumptions
- The backend supports state locking and Terraform produced a lock record or a backend-specific locking error.
- The responder has access to the same configuration, backend, workspace, and credentials as the failed run.
- CI, remote run, scheduler, and local execution histories are available for correlation.
- The organization has a protected location for state snapshots and incident evidence.
- Terraform state is treated as secret-bearing data and never stored in source control.
- The execution team can freeze new runs for one state during recovery.
- Backend-specific direct lock deletion is outside this Guide.
- Manual terraform state push is outside normal lock recovery and requires a separate high-risk plan.
- The guide covers Terraform CLI and remote backends, but backend service health and permissions remain provider-specific.
- All times are converted to UTC before comparing the lock, run, and provider timelines.
Key concepts
- State lock
- A backend coordination record that prevents two Terraform operations from writing the same state at once.
- Error acquiring the state lock
- Terraform could not obtain exclusive access for the current operation. It can indicate an active holder, stale record, contention, permission problem, or backend failure.
- Lock ID
- The unique identifier printed in Lock Info and required by force-unlock. HashiCorp describes it as a nonce that targets the intended lock.
- Who
- The identity string recorded by the lock holder. It is correlation evidence, not proof that the process is still alive or authorized.
- Operation
- The Terraform operation type that created the lock, such as apply. Its risk and expected duration guide the active-run investigation.
- Created
- The lock creation timestamp. Age alone never proves staleness because remote runs can wait for approval or provider operations.
- Backend
- The component that stores state and optionally implements locking. The same configuration can point to different state after initialization changes.
- Workspace
- A named state instance selected by the CLI or remote platform. Unlock decisions must refer to the exact workspace.
- Lineage
- A stable identity for one state history. A changed lineage usually means the responder is looking at another state.
- Serial
- A monotonically increasing state generation number. An unexplained increase signals another state write.
- Stale lock
- A lock left after its owning operation definitively ended and every potential writer is confirmed stopped.
- force-unlock
- Terraform command that removes one lock from the current configuration's backend without modifying infrastructure. It can enable dangerous concurrent writers if misused.
- Lock timeout
- A bounded period Terraform waits and retries normal acquisition while keeping locking enabled.
- State reconciliation
- Incident work that compares configuration, state, provider reality, and run history after possible concurrent or partial operations.
Fill these once. Every matching command and configuration block updates immediately; values stay in this page only.
Security and production boundaries
- Do not use -lock=false. HashiCorp explicitly does not recommend disabling state locking.
- Do not force-unlock another user's or runner's active operation.
- Do not automate force-unlock immediately after a timeout or process disappearance.
- Do not manually delete a lock object or row from backend storage through ad hoc provider commands.
- Do not paste Terraform state, plans, .terraform metadata, backend credentials, or raw variable values into tickets.
- Do not commit .terraform directories or state snapshots. Backend configuration and state can contain secrets.
- Do not pass backend credentials through -backend-config where they can be copied into .terraform or plan files.
- Do not use terraform state push -force as a lock repair. It can overwrite authoritative state despite lineage or serial protection.
- Keep provider credentials least privilege and remove them from the recovery shell after use.
- Require two-person review for production stale-lock classification and force-unlock.
- Freeze new writers for the affected state during the recovery window.
- Treat unexpected lineage, serial, backend, workspace, or provider activity as an integrity incident.
Stop before continuing if
- The backend, account, region, key, organization, root module, or workspace is uncertain.
- Any local, CI, remote, scheduler, or provider operation may still own or use the state.
- The lock record changes while the incident is being reviewed.
- The state cannot be pulled into an approved protected evidence location.
- The pre-recovery lineage does not match the intended environment.
- The error is permission denied, network timeout, throttling, unavailable, or another backend failure rather than an existing stale lock.
- The proposed solution uses -lock=false, manual lock-object deletion, or state push -force.
- The force-unlock approver has not reviewed the exact lock ID and active-run evidence.
- Another operator or automation starts a plan during the recovery window.
- State serial changes without a known successful operation.
- The post-recovery plan contains unexplained deletion, replacement, import, or broad drift.
- Provider audit logs show resource operations after the presumed lock owner ended.
command
Capture the complete lock error without bypassing it
Run a non-applying plan with refresh disabled and a short lock timeout from the same root module and identity that failed. Preserve the complete Lock Info block: ID, Path, Operation, Who, Version, Created, and Info. Terraform Error acquiring the state lock is a protective stop. Do not add -lock=false.
Why this step matters
The lock record is the primary evidence for identifying the owner and exact state. Bypassing it before capture can erase the only reliable coordination signal.
What to understand
Use -refresh=false so this diagnostic plan does not query and refresh every provider object before the lock question is resolved.
A plan does not apply infrastructure changes, but it normally acquires a state lock because it can read and potentially produce state-related results.
Keep the full lock ID. Do not transcribe a shortened value into the unlock command.
Record wall-clock time and timezone next to the error so Created can be compared with active run logs.
Store the transcript in a restricted location because backend paths, usernames, and workspace names can be sensitive.
System changes
- Writes a local evidence transcript.
- Attempts to acquire the backend lock but does not disable or remove it.
- May contact the backend and providers required to initialize the plan; no apply is performed.
Syntax explained
plan- Builds an execution plan; it never applies the proposed infrastructure changes.
-refresh=false- Uses the prior state view during this diagnostic instead of refreshing every remote object.
-lock-timeout=30s- Retries lock acquisition briefly before returning the lock record.
-input=false- Prevents an unattended diagnostic from waiting for variable prompts.
-no-color- Produces a stable transcript without terminal escape codes.
Values stay on this page and are never sent or saved.
terraform plan -refresh=false -lock-timeout=30s -input=false -no-color 2>&1 | tee "{{evidenceDir}}/lock-error.txt"Error: Error acquiring the state lock Error message: ConditionalCheckFailedException: The conditional request failed Lock Info: ID: 7c8f6a28-4bf3-44e6-a45f-2b4f54b9f982 Path: tf-state-prod/network/terraform.tfstate Operation: OperationTypeApply Who: ci-runner@build-1842 Version: 1.9.8 Created: 2026-08-23 16:41:12.890000 +0000 UTC Info:
Checkpoint:
Continue when
Stop when
If this step fails
The output has no Lock Info block
Likely causeThe backend or service returned a permission, network, authentication, or unsupported-locking error instead of an existing lock.
terraform versionterraform workspace show
ResolutionDiagnose backend access or availability. Never invent a lock ID or delete backend objects.
Security notes
- State paths and run identities can reveal environment design; restrict the transcript.
- Never pass -lock=false to work around this error.
Alternatives
- If the original failed apply already produced complete lock output, preserve that transcript and do not run another plan until the active-operation check.
Stop conditions
- Stop if the path or workspace is not the intended environment.
- Stop if the backend error is access denied, unavailable, or malformed rather than an existing lock.
command
Confirm the exact configuration, workspace, and initialized backend
Verify the working directory, Terraform binary, selected workspace, provider graph, and version-controlled backend block. The local .terraform directory records initialized backend details and can differ between checkouts; it can also contain sensitive backend configuration, so inspect it locally without publishing it.
Why this step matters
force-unlock targets the lock for the current configuration. A correct lock ID used from the wrong backend or workspace cannot safely recover the intended state.
What to understand
Confirm the root module and reviewed Git revision used by the active or failed run.
Read the backend block from version control. Do not print backend credentials or the full .terraform/terraform.tfstate file.
Compare workspace name, remote state key, bucket or workspace ID, account, region, and organization with the lock Path and run console.
terraform providers reads the initialized provider requirements; unexpected providers or modules indicate the wrong checkout.
A dirty working tree is not itself the lock cause, but it can make post-recovery plans incomparable.
System changes
- None. These commands inspect local configuration, workspace selection, provider requirements, and Git state.
Syntax explained
terraform workspace show- Prints the currently selected CLI workspace.
terraform providers- Shows provider requirements for the current configuration.
git rev-parse --show-toplevel- Confirms which repository and root contain the executed configuration.
pwd && terraform version && terraform workspace show && terraform providers && git status --short && git rev-parse --show-toplevel/srv/iac/network-live Terraform v1.9.8 on linux_amd64 prod Providers required by configuration: . └── provider[registry.terraform.io/hashicorp/aws] ~> 5.0 /srv/iac
Checkpoint:
Continue when
Stop when
If this step fails
terraform workspace show reports a different workspace
Likely causeThe shell or CI checkout selected another workspace than the incident target.
terraform workspace listgit status --short
ResolutionStop. Select or initialize the intended workspace only through the team's normal workflow, then re-collect evidence.
Security notes
- Do not commit or share .terraform; backend configuration can contain credentials.
- Do not include backend secrets in -backend-config command lines or tickets.
Alternatives
- For HCP Terraform, verify organization and workspace in the remote run UI and the configuration's cloud block instead of reading local backend internals.
Stop conditions
- Stop if any backend, account, region, key, organization, workspace, or repository identity is uncertain.
- Stop if local initialization appears stale or points to a retired backend.
command
Find every active writer before deciding the lock is stale
Check local processes, CI pipelines, scheduled jobs, HCP Terraform or Terraform Enterprise runs, and team activity for the exact state. Match the Lock Info Who, Operation, Created time, Terraform version, and run metadata. A process missing from the local host does not prove the lock is stale.
Why this step matters
HashiCorp warns that force-unlock while another holder is active can create multiple writers and corrupt state. The active-run search is the most important safety gate.
What to understand
Search the CI system by repository, workspace, commit, branch, runner, and start time.
For HCP Terraform or Terraform Enterprise, inspect queued, planning, policy-check, cost-estimation, awaiting-approval, applying, and cancellation states.
Check automation controllers, scheduled maintenance, chatops, and break-glass shells.
Contact the Who identity or owning team and ask for the run ID and current phase.
A network partition can leave the run active even when its log stream appears frozen; verify the executor and backend separately.
System changes
- None. The local command lists processes and UTC time.
Syntax explained
ps -eo pid,lstart,user,args- Shows process ID, start time, owner, and complete command for local correlation.
grep '[t]erraform'- Filters Terraform processes without matching the grep command itself.
date -u- Provides an unambiguous UTC comparison with the lock Created field.
ps -eo pid,lstart,user,args | grep '[t]erraform' && date -u24198 Sat Aug 23 16:40:58 2026 runner terraform apply -input=false tfplan Sat Aug 23 16:43:10 UTC 2026
Checkpoint:
Continue when
Stop when
If this step fails
No local process exists but CI shows an active apply
Likely causeThe lock belongs to a remote runner or service, not the current host.
terraform workspace showterraform version
ResolutionLet the remote operation finish or cancel it through the owning platform. Do not force-unlock from the local shell.
Security notes
- Restrict process and CI logs that contain variable values, backend paths, or cloud resource identifiers.
- Do not kill an apply process without its owner and recovery procedure; abrupt termination can leave provider operations in flight.
Alternatives
- On Windows, use Get-CimInstance Win32_Process filtered to terraform.exe and inspect the CI or remote-run consoles separately.
Stop conditions
- Stop if any apply, destroy, import, state mutation, or remote plan is still active or its status is unknown.
- Stop if the lock owner cannot be contacted and provider-side activity may still be running.
decision
Classify active lock, stale lock, contention, or backend failure
Use the lock record and run evidence to classify the incident. An active legitimate lock is not an error to repair. Short-lived contention should use a lock timeout. A stale lock is an orphaned lock from your own failed operation after every writer has stopped. Permission, consistency, throttling, network, or service failures require backend repair, not force-unlock.
Why this step matters
The same top-level error can represent healthy serialization, an orphan, or a failing backend. Each requires a different action.
What to understand
Active lock: the run exists and progresses. Wait, monitor, or cancel through the owner.
Contention: a valid operation should finish soon. Retry with an agreed -lock-timeout after it releases.
Stale lock: the operation ended or crashed, all writer locations are clear, the owner confirms it is abandoned, and the exact backend/workspace is known.
Backend failure: lock service or storage returns access denied, timeout, throttling, inconsistent data, unavailable, or credential errors.
Unknown: evidence is incomplete. Treat it as active and do not unlock.
System changes
- None. This is a documented decision gate.
Classification: active legitimate lock Owner: ci-runner build-1842 Action: wait for run; do not unlock Next review: 2026-08-23T16:50:00Z
Checkpoint:
Continue when
Stop when
If this step fails
The Created time is old but the remote run is still awaiting approval
Likely causeA remote execution platform intentionally retains coordination for the pending run.
Review the remote workspace run queueContact the run owner
ResolutionCancel or complete the run through the platform; do not bypass its coordination lock.
Security notes
- Require two-person review for production stale-lock classification.
- Do not let urgency turn an unknown lock into a stale lock.
Alternatives
- If normal contention is common, change automation to queue runs and use a bounded lock timeout rather than manual unlocks.
Stop conditions
- Stop unless the classification and evidence are recorded.
- Stop if any reviewer disagrees that the lock is stale.
command
Preserve restricted state metadata before any unlock
After confirming the exact backend and workspace, pull the current state into the protected incident location with restrictive permissions. Terraform state can contain passwords, tokens, private addresses, and provider data. Hash the file and extract only lineage, serial, and Terraform version for the review record; never paste the full state into chat, a ticket, or source control.
Why this step matters
The pre-recovery state and its identity are essential if an unlock exposes concurrent writes or reveals a later state mismatch. The hash proves which snapshot was reviewed.
What to understand
Use an encrypted evidence store with access limited to responders and an explicit retention policy.
state pull is read-only for the backend, but the local file contains the complete sensitive state.
Check that evidenceDir is outside the repository and not synchronized to an unapproved service.
Record only the lineage, serial, Terraform version, checksum, retrieval time, backend, workspace, and lock ID in the general incident ticket.
If state pull itself returns Error acquiring the state lock or backend access errors, preserve that output and escalate; do not switch to direct storage APIs.
System changes
- Reads the authoritative backend state.
- Writes a sensitive local state snapshot and SHA-256 checksum with restrictive process permissions.
Syntax explained
umask 077- Restricts newly created evidence files to the current user on POSIX systems.
terraform state pull- Reads and emits the current state snapshot without editing it.
sha256sum- Records a digest for later integrity comparison.
jq '{lineage,serial,terraform_version}'- Extracts non-resource state identity fields for the review record.
Values stay on this page and are never sent or saved.
umask 077; terraform state pull > "{{evidenceDir}}/state-before.json" && sha256sum "{{evidenceDir}}/state-before.json" > "{{evidenceDir}}/state-before.sha256" && jq '{lineage,serial,terraform_version}' "{{evidenceDir}}/state-before.json"{
"lineage": "9d4b66bc-39df-4a76-86c7-d408d6d74d22",
"serial": 184,
"terraform_version": "1.9.8"
}Checkpoint:
Continue when
Stop when
If this step fails
state pull returns access denied or backend unavailable
Likely causeCredentials, service health, network, or backend permissions are broken in addition to the lock error.
terraform workspace showterraform version
ResolutionRepair read access or backend availability with the backend owner. Do not force-unlock through direct storage manipulation.
Security notes
- Terraform state is secret-bearing data. Never commit, email, or paste it.
- Delete evidence only according to the incident retention policy, not immediately after success.
Alternatives
- On Windows, create the evidence file in an encrypted access-controlled directory, use terraform state pull with PowerShell redirection, and calculate Get-FileHash -Algorithm SHA256.
Stop conditions
- Stop if no approved location exists for the state snapshot.
- Stop if lineage, backend, workspace, or serial belongs to another environment.
instruction
Let an active operation finish or cancel it through its owner
When the lock is active, do not unlock it. Observe the owning run, wait for a healthy operation, or cancel it through the CI, HCP Terraform, Terraform Enterprise, scheduler, or operator workflow that created it. Confirm provider calls have stopped and allow Terraform to release the lock normally.
Why this step matters
Normal completion or platform-managed cancellation preserves Terraform's single-writer guarantee and cleanup path.
What to understand
A plan awaiting approval can remain intentionally active; cancel it in the remote platform rather than forcing its lock.
An apply cancellation can take time while providers finish or time out. Do not start another writer during cancellation.
Capture the owning run ID, cancellation request, final result, state serial, and lock release time.
After the owner reports completion, retry a read-only plan with a bounded lock timeout.
If the process crashed, confirm the executor is gone and no provider-side operation continues before classifying the lock as stale.
System changes
- Cancellation can interrupt the owning Terraform run and leave infrastructure partially changed. Use the platform's documented cancellation and incident procedure.
- No lock is manually removed in this step.
Run build-1842: cancelled by incident commander Terraform cancellation complete State lock released No provider operations active
Checkpoint:
Continue when
Stop when
If this step fails
Cancellation remains pending
Likely causeA provider operation is still running, the agent is unreachable, or the platform cannot deliver the cancellation.
Review the run event timelineInspect provider audit logs using read-only access
ResolutionKeep all other writers stopped and escalate to the execution-platform owner. Do not force-unlock while activity is uncertain.
Security notes
- Cancellation is operationally safer than a competing writer but may still leave partial infrastructure changes requiring reconciliation.
- Do not expose variable values or state outputs while sharing run evidence.
Alternatives
- For a short healthy operation, wait and use terraform plan -lock-timeout={{lockTimeout}} after it finishes.
Stop conditions
- Stop if the owner, run phase, or provider-side activity is unknown.
- Do not move to force-unlock until every active-operation signal is negative.
command
Retry normal locking with a bounded timeout
For ordinary contention or after the owner has completed, let Terraform wait for the lock through its supported timeout. This preserves locking and avoids races between polling scripts. Use a non-applying plan and inspect the result before any change.
Why this step matters
HashiCorp documents -lock-timeout as the supported way to retry lock acquisition. It is safer than -lock=false or repeated force-unlock attempts.
What to understand
Set a timeout long enough for the known active operation but short enough for the incident response.
Keep -refresh=false for this coordination check; run a normal refreshed plan only after state locking is healthy.
Observe both acquisition and release. A process that exits before release may recreate the stale-lock condition.
If the lock ID or owner changes, another writer started. Return to the active-writer inventory.
Do not run multiple retrying plans from parallel terminals.
System changes
- Attempts to acquire and release the normal state lock.
- Creates an in-memory plan and may write local logs; it does not apply infrastructure.
Syntax explained
-lock-timeout={{lockTimeout}}- Retries acquiring the state lock for the specified Terraform duration.
-refresh=false- Limits this check to prior state rather than refreshing provider objects.
-input=false- Fails rather than waiting for interactive variable input.
Values stay on this page and are never sent or saved.
terraform plan -refresh=false -lock-timeout={{lockTimeout}} -input=false -no-colorAcquiring state lock. This may take a few moments... No changes. Your infrastructure matches the configuration. Releasing state lock. This may take a few moments...
Checkpoint:
Continue when
Stop when
If this step fails
A new lock ID or Who value appears
Likely causeAnother pipeline or operator attempted a run during recovery.
ps -eo pid,lstart,user,args | grep '[t]erraform'Review CI and remote run queues
ResolutionFreeze writers, identify the new owner, and restart the classification. Do not unlock either record blindly.
Security notes
- Keep the recovery window coordinated so only one diagnostic plan runs.
- Do not add -lock=false.
Alternatives
- Central run queues can serialize retries without multiple local clients; use them when they are the authoritative execution path.
Stop conditions
- Stop if the retry reveals another active writer, state mismatch, permission error, or backend unavailability.
command
Force-unlock only the confirmed stale lock ID
Use terraform force-unlock only after the stale classification is approved, every writer is stopped, the exact backend and workspace are confirmed, and the pre-recovery state is protected. Enter the complete lock ID from the captured Lock Info and keep the interactive confirmation. HashiCorp warns that unlocking another holder can create multiple writers.
Why this step matters
The unique lock ID acts as a nonce and limits the command to the reviewed lock. Interactive confirmation is a final human safety barrier.
What to understand
Read the backend, workspace, state path, lock ID, owner, created time, and approval aloud or in the change record immediately before confirmation.
Do not use -force in an interactive incident; it removes the final confirmation prompt.
The command removes a lock for the current configuration. It does not change infrastructure, but it enables another writer.
Do not manually delete lock objects or rows from S3, DynamoDB, Azure Blob, Consul, GCS, or other backend internals unless the backend owner has a separate vendor-approved recovery procedure.
Capture command output and UTC completion time.
System changes
- Removes the selected state lock from the configured backend.
- Does not itself modify infrastructure or the Terraform state snapshot.
- Permits subsequent state-writing operations, so an incorrect decision can enable concurrent writers.
Syntax explained
force-unlock- Asks the current backend to remove a specific state lock.
{{lockId}}- The complete unique ID printed by the failed lock acquisition; it protects against unlocking a different record.
interactive confirmation- Requires an explicit yes after Terraform repeats the danger.
Values stay on this page and are never sent or saved.
terraform force-unlock "{{lockId}}"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. Enter a value: yes Terraform state has been successfully unlocked!
Checkpoint:
Continue when
Stop when
If this step fails
Terraform says the lock ID does not match
Likely causeThe lock was released, replaced, or the current configuration points to another backend or workspace.
terraform workspace showterraform plan -refresh=false -lock-timeout=30s -input=false -no-color
ResolutionDo not retry with another ID until the new lock and owner are fully investigated.
Security notes
- Production force-unlock should require two-person review.
- Never automate discovery and force-unlock as one unattended action.
Alternatives
- If an active or remote-managed run exists, cancel it through its owner and let normal unlocking occur.
Stop conditions
- Stop if any active writer signal returns, the lock record changes, confirmation evidence is incomplete, or the state snapshot cannot be preserved.
- Stop if the command targets local state; HashiCorp notes local state cannot be unlocked by another process.
verification
Verify state identity, locking, and the next plan
Immediately pull state metadata again, compare lineage and serial with the protected pre-recovery snapshot, and run one plan that acquires and releases the lock. Then run a normal refreshed plan under review. A serial increase must be explained by a legitimate operation; a lineage change is a hard stop.
Why this step matters
Unlock success is not recovery proof. State identity and normal lock behavior must be intact before any apply resumes.
What to understand
Compare lineage exactly with state-before.json.
A higher serial may be valid only if a known operation wrote state; correlate it with the run and provider audit logs.
Review the plan for unexpected creates, deletes, replacements, imports, or drift.
Use -detailed-exitcode in automation: 0 means no changes, 2 means a plan exists, and 1 means error.
Keep all other writers frozen until this verification releases the lock.
System changes
- Reads state and acquires/releases the normal lock.
- The refresh-disabled plan does not apply infrastructure.
Syntax explained
lineage- Identifies the state history. A different lineage normally means a different state.
serial- Monotonically increases when Terraform writes a new state snapshot.
-lock-timeout={{lockTimeout}}- Proves the backend can serialize the verification plan.
Values stay on this page and are never sent or saved.
terraform state pull | jq '{lineage,serial,terraform_version}' && terraform plan -refresh=false -lock-timeout={{lockTimeout}} -input=false -no-color{
"lineage": "9d4b66bc-39df-4a76-86c7-d408d6d74d22",
"serial": 184,
"terraform_version": "1.9.8"
}
Acquiring state lock. This may take a few moments...
No changes. Your infrastructure matches the configuration.
Releasing state lock. This may take a few moments...Checkpoint:
Continue when
Stop when
If this step fails
State serial increased unexpectedly
Likely causeAnother writer completed during recovery or backend state changed outside the reviewed sequence.
Compare the protected snapshotsReview CI, remote run, and provider audit timelines
ResolutionFreeze writers and reconcile the authoritative state before any apply.
Security notes
- Do not share pulled state while comparing metadata.
- An unexpected lineage is a state-identity incident.
Alternatives
- Use the remote execution platform's speculative plan and run timeline when it is the authoritative, locking-aware path.
Stop conditions
- Stop on lineage change, unexplained serial increase, missing resources, unexpected replacements, or another lock error.
warning
Recover if the wrong lock was removed
If evidence shows an active holder continued after force-unlock, declare a state incident immediately. Stop all writers and do not try to recreate a lock manually. Preserve both state views and provider activity, then select one incident owner to reconcile real infrastructure and Terraform state.
Why this step matters
A removed lock cannot be rolled back as a transaction. The priority is to prevent a second write and preserve enough evidence for safe reconciliation.
What to understand
Cancel queued runs and block merge or deployment automation for the affected state.
Preserve every plan, state snapshot, checksum, run log, and provider audit event.
Compare resource addresses, lineage, serial, and timestamps without editing state JSON by hand.
Inspect provider reality with read-only tools and identify partial creates, updates, or deletes.
Use terraform import, state mv, state rm, or provider-specific recovery only through a separate reviewed procedure.
Never push the older snapshot merely because it existed before the incident; it may erase legitimate newer bindings.
System changes
- Operationally freezes Terraform writers and deployment automation.
- Further recovery actions are intentionally outside this Guide and require a dedicated incident plan.
INCIDENT: concurrent Terraform writers possible Writers frozen: yes Current state preserved: yes Pre-unlock state preserved: yes Lineage comparison: pending Serial comparison: pending Next apply: blocked
Checkpoint:
Continue when
Stop when
If this step fails
Two state snapshots have the same lineage but different serials
Likely causeConcurrent or sequential writers produced different generations.
jq '{lineage,serial,terraform_version}' {{evidenceDir}}/state-before.jsonterraform state pull | jq '{lineage,serial,terraform_version}'
ResolutionUse run and provider evidence to identify the authoritative latest bindings; do not force a state push.
Security notes
- State snapshots and provider logs contain secrets and infrastructure identifiers.
- Treat concurrent writers as a production integrity incident.
Alternatives
- Engage HashiCorp or backend vendor support when the state store or run platform has inconsistent coordination data.
Stop conditions
- Do not resume Terraform until one authoritative state and one execution owner are established.
instruction
Prevent recurrent lock incidents
Move routine operations into one queue per state, use bounded lock timeouts, record run ownership, and make cancellation and stale-lock review explicit. Monitor backend availability and permissions. Force-unlock should remain a rare, human-reviewed recovery action rather than an automation primitive.
Why this step matters
Most lock incidents are coordination, cancellation, or backend-health failures. A single execution path and visible ownership reduce both stale locks and unsafe manual recovery.
What to understand
Use HCP Terraform, Terraform Enterprise, or a CI concurrency key to serialize each state.
Include run ID, state, workspace, owner, commit, and cancellation link in change notifications.
Set a bounded -lock-timeout for plans and applies instead of retry loops or -lock=false.
Alert on backend availability, permissions, throttling, lock duration, and abandoned runners.
Test cancellation and stale-lock recovery in a non-production state.
Keep remote state versioning, encryption, restricted access, and backup policy enabled according to backend guidance.
Review provider and Terraform upgrades for backend and locking changes.
System changes
- Process, CI, monitoring, and backend changes require separate reviewed implementation.
State: network-prod Authoritative runner: HCP Terraform workspace network-prod Concurrent runs: queued Lock timeout: 5m Force-unlock approval: two responders Backend health alert: enabled State backup policy: verified
Checkpoint:
Continue when
Stop when
If this step fails
Multiple CI systems can still apply the same state
Likely causeConcurrency controls exist only inside each system, not across the shared backend.
Inventory pipelines by backend key and workspaceReview recent lock Who values
ResolutionChoose one authoritative writer or implement cross-system coordination that preserves backend locking.
Security notes
- Do not store backend credentials in configuration, plans, or .terraform artifacts.
- Least-privilege state access and versioned backups reduce the blast radius of a lock incident.
Alternatives
- Split unrelated infrastructure into separately owned states when coordination and blast radius justify the added dependencies.
Stop conditions
- Do not automate force-unlock without human evidence review and an exact lock ID.
Finish line
Verification checklist
terraform version && terraform workspace showThe expected Terraform version and exact target workspace are printed.terraform state pull | jq '{lineage,serial,terraform_version}'The expected lineage is present and the serial is at least the recorded pre-recovery value.terraform plan -refresh=false -lock-timeout={{lockTimeout}} -input=false -no-colorThe plan starts after acquiring the lock and exits without Error acquiring the state lock.terraform plan -lock-timeout={{lockTimeout}} -input=false -detailed-exitcode -no-colorExit 0 means no changes or exit 2 means a reviewed plan; exit 1 or unexpected replacements block further action.ps -eo pid,lstart,user,args | grep '[t]erraform'Only the expected diagnostic command is present locally, and CI or remote-run consoles show no unowned active writer.Recovery guidance
Common problems and safe checks
Terraform prints Error acquiring the state lock with a recent active apply
Likely causeA legitimate writer owns the lock.
Review Lock Info Who, Operation, and CreatedInspect the matching CI or remote run
ResolutionWait for the run or cancel it through its owner. Do not force-unlock.
Error acquiring the state lock appears during two simultaneous CI jobs
Likely causePipeline concurrency is not serialized for the shared state.
Compare run start times and state pathsReview CI concurrency settings
ResolutionLet one run finish, retry the other with -lock-timeout, and add one concurrency key per state.
The lock owner process crashed and no run remains
Likely causeAutomatic unlock failed after an abnormal exit.
Search all writer locationsPull and checksum stateCompare provider audit activity
ResolutionAfter two-person stale classification, use the exact terraform force-unlock lock ID.
force-unlock reports a lock ID mismatch
Likely causeThe original lock was released or replaced, or the current configuration targets a different state.
terraform workspace showRetry a refresh-disabled plan with a short lock timeout
ResolutionRestart evidence collection for the current lock. Never substitute a guessed ID.
Terraform reports access denied while acquiring the lock
Likely causeBackend IAM or credentials do not permit lock operations.
terraform versionConfirm backend and workspaceReview backend audit logs
ResolutionRepair least-privilege backend access. Force-unlock cannot fix permissions.
The backend times out or is unavailable
Likely causeState storage or lock service health, routing, DNS, throttling, or regional availability is failing.
Review the backend status and monitoringTest approved read access
ResolutionRestore backend health and retry normal locking; do not delete coordination data during an outage.
A remote run is awaiting approval for hours
Likely causeThe platform intentionally holds or coordinates the workspace run.
Inspect the remote run state and queueContact the run owner
ResolutionApprove, discard, or cancel through the platform. Age alone does not make the lock stale.
state pull returns a different lineage
Likely causeThe shell is initialized to another backend or workspace, or the state was replaced.
terraform workspace showInspect the version-controlled backend block
ResolutionStop and identify the authoritative state before any unlock.
State serial increased during recovery
Likely causeAnother writer completed or a backend/state operation changed the snapshot.
Compare state checksums and serialsReview run and provider audit timelines
ResolutionFreeze writers and reconcile state; do not proceed with a routine plan.
The lock reappears immediately after force-unlock
Likely causeAn active or queued writer acquired it, or automation is retrying.
Inspect the new Lock InfoReview CI and remote queues
ResolutionStop the writer and freeze automation. Treat the original stale classification as invalid.
The post-unlock plan proposes widespread recreation
Likely causeWrong state/workspace, missing provider configuration, state loss, or real drift.
Compare lineage and serialterraform providersReview the protected pre-recovery snapshot metadata
ResolutionDo not apply. Begin state reconciliation and restore the correct execution context.
A local terraform.tfstate lock cannot be cleared remotely
Likely causeThe local backend uses operating-system file locking tied to a process.
ps -eo pid,lstart,user,args | grep '[t]erraform'Inspect file ownership and working directory
ResolutionResolve the local process or filesystem condition. HashiCorp states local state cannot be unlocked by another process.
Cancellation finished but provider operations continue
Likely causeThe provider API accepted asynchronous work before Terraform stopped.
Inspect provider audit logs and operation statusKeep all Terraform writers frozen
ResolutionWait or recover the provider operation, then reconcile state before normal planning.
Reference
Frequently asked questions
What does Terraform Error acquiring the state lock mean?
Terraform could not obtain exclusive backend coordination for the current operation. Another run may be active, a previous run may have left a stale lock, or backend permissions, availability, or consistency may be failing.
Can I add -lock=false to continue?
No. HashiCorp does not recommend disabling locking because concurrent writers can corrupt or conflict with state.
When is terraform force-unlock appropriate?
Only for your own confirmed stale lock after every possible writer is stopped, the exact backend and workspace are verified, state is preserved, and the unique lock ID is reviewed.
Does terraform force-unlock change infrastructure?
The command itself does not modify infrastructure. It removes a coordination lock, which can allow another command to write state or infrastructure and is dangerous if the original holder is active.
How do I know whether a lock is stale?
Correlate Who, Operation, Created, lock path, run IDs, local processes, CI, schedulers, remote runs, and provider activity. Age or a missing local process alone is insufficient.
Why should I keep the interactive confirmation?
It is the last human checkpoint after Terraform identifies the danger. Avoid -force during interactive recovery.
Should I delete the lock directly in S3, DynamoDB, Azure, GCS, or Consul?
Not through an ad hoc command. Use Terraform force-unlock for the exact reviewed lock or a separate backend-vendor recovery procedure.
Why preserve state before unlocking?
If another writer existed or state changes afterward, the protected snapshot, lineage, serial, and checksum are necessary to establish what was authoritative.
Can I restore the old state if something goes wrong?
Not blindly. A newer state may contain legitimate bindings. Freeze writers, compare lineage, serial, runs, and provider reality, then use a dedicated reconciliation plan.
What is the safe response to normal lock contention?
Let the active run finish and retry with a bounded -lock-timeout. Keep locking enabled.
What if the backend returns permission denied or timeout instead of Lock Info?
Treat it as backend access or availability trouble. Repair IAM, credentials, routing, throttling, or service health; force-unlock is not the remedy.
How often should this guide be reviewed?
Review it within 90 days and whenever Terraform, the backend, HCP Terraform, CI concurrency, state ownership, cancellation behavior, or incident procedures change.
Recovery
Rollback
Removing a state lock is not transactionally reversible. Terraform force-unlock does not modify infrastructure, but an incorrect unlock can allow multiple writers. Recovery is to stop every writer, preserve state and provider evidence, compare lineage and serial, and reconcile the authoritative state before any new apply.
- Immediately stop or cancel every local, CI, scheduler, and remote Terraform writer for the affected state.
- Preserve current backend state, the pre-unlock snapshot, lock output, run logs, provider audit logs, and checksums in the restricted incident location.
- Compare state lineage, serial, resource addresses, and the last known successful run. Never push an older state merely to restore a lock.
- If concurrent operations changed infrastructure or state, assign one incident owner to reconcile provider reality, Terraform state, and configuration through reviewed state commands or imports.
- Do not use terraform state push -force. HashiCorp describes manual state push as extremely dangerous; any push needs a separate recovery plan, backup, lineage review, and senior approval.
- Resume planning only after one authoritative state is established, all writers are coordinated, and normal locking succeeds.
Evidence