Skip to main content

Troubleshooting — The Builder's Problem Desk

Every Terraform user eventually meets a scary error. This is the Problem Desk: what the message means, why it happened, and how to get out. Each problem follows the same Problem → Cause → Fix rhythm you know.

1 · "Error acquiring the state lock"​

Problem

terraform apply waits, then fails with Error acquiring the state lock.

Cause: Someone else (or a stuck CI job) is running a Terraform command that holds the lock on the remote state. The lock exists to prevent two people from building over each other.

Fix:

# Wait a moment and retry — the other run may finish quickly
terraform plan

If the lock is stuck (a crashed process left it behind), force-release it — but only after confirming no one is genuinely running:

terraform force-unlock <LOCK_ID>

The lock ID is printed in the error message.

Remember

A lock error is Terraform protecting you. Always confirm a run isn't actually in progress before force-unlocking.

2 · The plan unexpectedly says "will destroy"​

Problem

You run terraform plan and something you care about is listed under will destroy — or worse, a resource will be replaced.

Cause (usually one of):

  • The resource was removed from the configuration (deleted the block, or a for_each key disappeared).
  • The resource was renamed in config — Terraform treats it as delete-old + create-new.
  • An argument that can't be changed in place forces replacement.

Fix: Read the plan carefully before applying.

terraform plan
  • Intended removal? Fine — let it destroy.
  • Renamed a resource? Use terraform state mv to rename it in state without touching the live resource, then apply.
terraform state mv aws_s3_bucket.old_name aws_s3_bucket.new_name
Careful

If a plan says a database will be replaced, stop and check — that usually means data loss. Look for "forces replacement" in the plan output.

3 · Drift — resources changed outside Terraform​

Problem

A plan shows changes to resources you didn't edit — because someone changed them in the AWS console.

Cause: Drift. Reality no longer matches state.

Fix: Refresh state to match reality, then review the true diff:

terraform apply -refresh-only
terraform plan

Now plan shows only the difference between blueprint and reality. Either re-apply to restore the blueprint, or update the blueprint to accept the change.

4 · Credentials errors — "no valid credential sources"​

Problem

terraform plan fails with no valid credential sources found or an access-denied error.

Cause: The AWS provider can't find credentials. Terraform looks in order: environment variables, shared config (~/.aws/credentials), then IAM roles.

Fix:

# Make sure the keys are actually exported
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY

# Or point at a named profile
export AWS_PROFILE=my-profile
Remember

Each terminal session needs its own exports — close the terminal and the keys are gone. This is why teams use shared config files or IAM roles instead.

5 · Backend / state file errors​

Problem

Errors like initialization required, backend configuration changed, or state file not found.

Cause: Your working directory isn't initialized for this backend, or the backend block changed.

Fix:

terraform init

When you add or change a backend block, init reconfigures and offers to migrate the existing state to the new location:

terraform init -migrate-state

6 · "Inconsistent dependency lock file"​

Problem

terraform init refuses with the dependency lock file is inconsistent.

Cause: terraform.lock.hcl pins provider versions, but the current config (or your checksums) don't match — usually after upgrading a provider or pulling a teammate's change.

Fix:

terraform init -upgrade

This refreshes the lock file to match the current configuration. Commit the updated lock file so the team stays in sync.

7 · "Resource already exists" — or resources created outside Terraform​

Problem

Apply fails because the resource already exists — it was created manually, or is in another Terraform state.

Cause: Terraform doesn't know about it. The register has no entry for that bucket/instance.

Fix: Import it into state, then Terraform will manage it:

terraform import aws_s3_bucket.archive campus-library-archive

Then run plan — it will show what differs from your blueprint.

8 · Validation errors on validate or plan​

Problem

An HCL error — an unknown argument, a missing closing brace, a wrong type.

Cause: A syntax or type mistake in the blueprint.

Fix:

terraform fmt # auto-fix spacing/indentation
terraform validate # fresh error report

validate points at the exact block and line. Most validation errors are a missing brace or a list passed where a string was expected.

Still stuck?​

The Problem Desk always starts with the same two steps:

terraform plan # what does Terraform think reality should be?
terraform state list # what does the register say exists?

If you can answer "what's in state?" and "what does the plan want to do?", you can usually spot the mismatch yourself. And if a term confuses you, the Glossary is one click away.