DEV Community

Haripriya Veluchamy
Haripriya Veluchamy

Posted on

I Fixed a Terraform State Lock Issue in GitHub Actions Here’s What I Learned

When you start running Terraform inside CI/CD pipelines like GitHub Actions, state management becomes a silent troublemaker.
Recently, I hit one of those classic issues:

Error: Error acquiring the state lock
state blob is already locked
Enter fullscreen mode Exit fullscreen mode

And the pipeline refused to continue.

If you’ve ever seen this, trust me you’re not alone. Here’s exactly how it happened, how I fixed it, and what you should always remember to avoid getting stuck like this again.


❗ The Issue: Terraform State Blob Got “Leased”

Terraform uses state locking to prevent multiple processes from modifying the state at the same time.

In my case, the state was stored in Azure Blob Storage.
During a GitHub Actions run:

  • The job acquired a lease on the blob
  • The job got interrupted
  • The lease never got released

So when the next GitHub Actions workflow started, Terraform immediately failed with:

state blob is already locked
Enter fullscreen mode Exit fullscreen mode

When I opened the Azure Blob container, the state file showed:

👉 Leased

That’s when I realized the lock was stuck at the storage level.


🔧 How I Diagnosed It

Three things told me the lock was real:

1. Terraform showed the same lock ID repeatedly

ID: 6a8f9229-xxxx
Who: runner@githubactions
Enter fullscreen mode Exit fullscreen mode

2. My local terraform force-unlock failed

The CLI told me:

local state cannot be unlocked by another process
Enter fullscreen mode Exit fullscreen mode

This showed that the lock wasn’t local it was in Azure.

3. Azure Blob Portal confirmed “Leased” status

Inside the container:

newsraag-prod.tfstate State: Leased
Enter fullscreen mode Exit fullscreen mode

So the GitHub Actions runner died, but the backend still thought it was running.


🛠️ The Fix: Break the Lease Manually

The only clean solution:

👉 Break the lease directly in Azure Blob Storage

Steps:

  1. Go to Azure Portal
  2. Open your Storage Account
  3. Go to Containers → open your Terraform state container
  4. Click your .tfstate file
  5. Choose Break Lease

Within seconds, the blob state changed to:

State: Broken

After this, I re-ran the GitHub Action it worked perfectly.


🧠 What You Should Remember (Very Important)

State lock issues happen in almost every team using Terraform.
Here are the important lessons I learned — and the practices you should follow too.


1. Never Run Parallel Terraform Jobs for the Same State

If two pipelines hit the same state file → deadlock.

Use GitHub Actions concurrency control:

concurrency:
  group: terraform-prod
  cancel-in-progress: false
Enter fullscreen mode Exit fullscreen mode

2. Add Lock Timeout to Terraform Commands

Instead of failing instantly, Terraform will wait for the lock:

terraform plan -lock-timeout=300s
terraform apply -lock-timeout=300s
Enter fullscreen mode Exit fullscreen mode

3. Don’t Cancel Terraform Pipelines Mid-Way

Cancelling the job leaves Azure Blob leases behind.

Let the job finish unless absolutely necessary.


4. Use Separate State Files for Each Environment

Do NOT use the same state file for dev, stage, and prod.

Example:

dev.tfstate
stage.tfstate
prod.tfstate
Enter fullscreen mode Exit fullscreen mode

5. Break Lease ONLY When You’re Sure No Job Is Running

Breaking the lease while Terraform is actively writing = corrupted state.

Always confirm:

  • No other Terraform processes
  • No pipeline in progress

✨ Bonus: Recommended GitHub Actions Pattern

Here’s the workflow I now use:

concurrency:
  group: terraform-${{ github.ref_name }}
  cancel-in-progress: false

steps:
  - name: Terraform Init
    run: terraform init -lock-timeout=300s

  - name: Terraform Plan
    run: terraform plan -lock-timeout=300s

  - name: Terraform Apply
    if: github.ref == 'refs/heads/main'
    run: terraform apply -lock-timeout=300s -auto-approve
Enter fullscreen mode Exit fullscreen mode

This avoids 99% of locking issues.


🏁 Final Thoughts

This issue taught me one big lesson state is the heart of Terraform, and anything that interrupts it can break the entire pipeline.

But once you understand:

  • how locking works
  • where leases get stuck
  • how to break them safely
  • and how to prevent them

…you’ll never panic when you see the “state blob is already locked” error again.

If you’re using Terraform in CI/CD pipelines, keep this checklist handy. It will save you hours of debugging.


Top comments (0)