LearnDevOpsHands-On Labs
Troubleshooting Matrix/Terraform. Error acquiring the state lock
TerraformCritical Severity

Terraform. Error acquiring the state lock

Fix "Error acquiring the state lock": read the lock info, wait if a run is live, otherwise run terraform force-unlock LOCK_ID. Covers S3 and DynamoDB backends.

Observed Error Signature / Log Pattern
Error: Error acquiring the state lock

Incident Overview

TerraformTerraform

Fix "Error acquiring the state lock": read the lock info, wait if a run is live, otherwise run terraform force-unlock LOCK_ID. Covers S3 and DynamoDB backends.

medium fix·6 min read

By Vishvesh Patel·DevOps Engineer·Updated 16 September 2026

BASHDiagnostic / remediation command
Error: Error acquiring the state lock

Error message: operation error DynamoDB: PutItem, ConditionalCheckFailedException
Lock Info:
  ID:        8f3c1e2a-4b7d-11ef-9c2a-0242ac120002
  Path:      acme-tfstate/production/terraform.tfstate
  Operation: OperationTypeApply
  Who:       alice@laptop
  Created:   2026-09-16 09:14:22.481 +0000 UTC

Do this first3 steps

Run these in order. Each one tells you what its output means before you change anything.

• Wait for it, because most locks are not stale

Waits instead of failing immediately. A CI run or a colleague's apply usually finishes inside that window. The error names Who and Created. Ask that person before you break anything.

• Only once you are certain nothing is running, break it

The ID comes from the error message. Breaking a lock while an apply is genuinely in flight can corrupt state. This is the one genuinely dangerous step on the page.

• If state is already damaged, recover from a version

With bucket versioning on, download the last good version and terraform state push it. Without versioning there is no undo at all, so turn it on before you need it.

Terraform locks state before any operation that could write to it, so two applies cannot run at once and corrupt each other. This error means the lock is already held.

The lock is doing its job far more often than it is broken. Before reaching for force-unlock, work out which situation you are in, because breaking a live lock is how state actually gets corrupted.

BASHDiagnostic / remediation command
terraform apply -lock-timeout=10m

Read the lock info first

Terraform prints everything you need:

Three fields decide what to do:

A lock created two minutes ago by a colleague running an apply is not stuck. Wait.

A lock created three hours ago by a CI runner that no longer exists is stuck, and safe to break once you have confirmed nothing is running.

BASHDiagnostic / remediation command
Lock Info:
  ID:        8f3c1e2a-4b7d-11ef-9c2a-0242ac120002
  Operation: OperationTypeApply
  Who:       alice@laptop
  Created:   2026-09-16 09:14:22.481 +0000 UTC

When it is genuinely a live lock

Someone or something is mid-operation. Options, in order:

Wait. Most applies finish in minutes.

Wait automatically, which is the right default in CI:

Terraform retries for that long before failing. Two pipelines that would otherwise collide simply queue.

Ask the person named in Who. Obvious, and routinely skipped.

BASHDiagnostic / remediation command
terraform apply -lock-timeout=10m

When the lock is genuinely stuck

A process killed mid-operation: a cancelled CI job, a closed laptop, a network drop, Ctrl-C at the wrong moment. Leaves the lock behind with nothing holding it.

Before unlocking, establish that nothing is running. Specifically:

The ID comes from the error message. Terraform asks for confirmation, and -force skips the prompt, which you should not use interactively.

• Why breaking a live lock is dangerous

If an apply genuinely is running and you force-unlock, a second apply can start against the same state. Both write to it, and the one that finishes last overwrites the other's record.

The result is state that does not match reality: resources exist that Terraform does not know about, and resources in state that were never created. Recovering means importing and removing entries by hand, and on a large configuration that is a genuinely bad day.

This is the one Terraform operation where being slow is correct.

BASHDiagnostic / remediation command
terraform force-unlock 8f3c1e2a-4b7d-11ef-9c2a-0242ac120002

Recovering if state is already corrupted

Enable versioning on your state bucket before you need it, that is the difference between a five-minute recovery and a rebuild.

Then run a plan and read it extremely carefully before applying anything.

BASHDiagnostic / remediation command
aws s3api list-object-versions \
  --bucket acme-tfstate \
  --prefix production/terraform.tfstate \
  --query 'Versions[:5].[VersionId,LastModified,Size]' --output table

Backend-specific notes

S3 with native locking: modern Terraform supports use_lockfile = true, which stores a lock object in S3 itself and removes the DynamoDB requirement:

S3 with DynamoDB: the older pattern. ConditionalCheckFailedException in the error means the lock row already exists. You can see it directly:

Deleting that row by hand works and is strictly worse than force-unlock, which performs the same operation with a confirmation prompt and correct handling of the digest entry.

Terraform Cloud / HCP: locks are managed in the UI, and a run can be discarded there. force-unlock does not apply.

BASHDiagnostic / remediation command
terraform {
  backend "s3" {
    bucket       = "acme-tfstate"
    key          = "production/terraform.tfstate"
    region       = "eu-west-1"
    encrypt      = true
    use_lockfile = true
  }
}

Stopping it recurring

The concurrency control is the highest-value one. A pipeline configured so two merges cannot apply the same workspace simultaneously removes the common cause entirely, and queueing at the CI layer gives a clearer outcome than a lock timeout.

A checklist

Frequently Asked Questions

What does "Error acquiring the state lock" mean?

Terraform locks the state file before any operation that could write to it, so two runs cannot modify it simultaneously and corrupt each other. This error means something already holds that lock, usually a colleague or a CI job that is genuinely mid-operation, and sometimes a process that died and left the lock behind. The lock info Terraform prints tells you which: check who holds it, when it was created, and what operation it was performing.

Is terraform force-unlock safe?

Only when you have confirmed nothing is actually running. Breaking a live lock allows a second apply to start against the same state, and whichever finishes last overwrites the other's record. Leaving state that does not match reality, with resources missing from it and entries for things that were never created. Recovering means importing and removing state entries by hand. Check your CI system and ask whoever is named in the lock before running it.

How do I find the lock ID for force-unlock?

Terraform prints it in the error message under Lock Info as ID. Copy that value into terraform force-unlock <ID>. If you have lost the output, running any Terraform command against the workspace produces the error again with the same ID. For a DynamoDB backend you can also read the lock row directly with aws dynamodb get-item, though force-unlock is the correct tool because it handles the digest entry properly.

How do I prevent state lock errors in CI/CD?

Set -lock-timeout=10m on plan and apply so a run waits for the lock rather than failing immediately, which makes concurrent pipelines queue. Add concurrency controls at the CI layer so only one run per workspace executes at a time, which is the more reliable fix since queueing there gives a clearer outcome than a timeout. Keeping separate state per environment also helps, since a staging run then cannot block a production one.

Can I just delete the DynamoDB lock row?

It works, and terraform force-unlock is better. The command does the same thing with a confirmation prompt, validates the lock ID you supply against the one actually held, and handles the accompanying digest entry correctly. Deleting rows by hand risks removing the wrong one or leaving the digest inconsistent. Either way, the important step is the same: confirm nothing is genuinely running first.

Do I still need a DynamoDB table for Terraform state locking?

Not on recent versions. Terraform now supports native S3 locking via use_lockfile = true in the backend block, which stores a lock object alongside the state and removes the separate table entirely. One less resource to provision, pay for and manage. The DynamoDB pattern remains supported and is what older configurations use, so you will encounter both. If you are setting up a new backend, prefer the native option.

Reference and practice

Learn the underlying concept

Other Terraform errors

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Get notified about new tutorials and features.

• Roadmaps

• Interview Prep

• Certifications

• Company

© 2026 DevOpsLesson. All rights reserved.

Need to practice this scenario?

Simulate this error condition and practice recovery commands safely in our in-browser terminal.

Open Terraform Sandbox