Most Terraform incidents are state problems, not configuration problems. Work through these in order before reaching for anything destructive.
State Lock
Terraform locks state before any operation that could write to it, to stop two applies from racing. A lock survives its owning process crashing (Ctrl-C during apply, a killed CI job), leaving state locked with nothing actually running.
Confirm nothing is actually running
Check CI for an in-progress or recently killed run, and ask the team before assuming the lock is stale — force-unlocking a lock held by a genuinely running apply can corrupt state.
Read the lock error for the lock ID
Error: Error acquiring the state lock
Lock Info:
ID: 5c4c02f4-1234-5678-90ab-cdef01234567
Path: env:/prod/terraform.tfstate
Operation: OperationTypeApply
Who: ci-runner@build-042Force-unlock using that ID
terraform force-unlock 5c4c02f4-1234-5678-90ab-cdef01234567Releases the lock. Only run this after confirming the operation that created it is genuinely dead — not just slow.
Corrupted or Out-of-Sync State
Pull state and inspect it
terraform state pullDownloads the raw state JSON so you can inspect it directly, or diff it against a known-good backup.
Check for drift before touching anything
terraform plan -refresh-onlyShows what's actually different between state and real infrastructure, without writing anything.
Restore from backup if state is genuinely corrupted
Terraform writes a terraform.tfstate.backup before most operations that modify state. If a bad push or an
interrupted apply corrupted the current state file, this is usually the fastest recovery path.
terraform state push terraform.tfstate.backupOverwrites remote state with the local backup file. Confirm the backup is actually newer and correct before pushing — this replaces the team's source of truth.
Backend Changed Unexpectedly
terraform init -reconfigureRe-points Terraform at the backend defined in configuration, discarding any stale cached backend settings, without attempting to migrate old state.
Two backends, two states
If a teammate changed the backend block and ran init -migrate-state locally without telling anyone, there may
now be two separate state files. Confirm which one is authoritative with terraform state list on each before
writing to either.
Resource Already Exists
Error: A resource with the ID ... already exists means the resource is real, but not in Terraform's state — usually
created manually, or previously managed by a different state file.
terraform import aws_instance.example i-0123456789abcdef0Brings the existing resource under management instead of trying to recreate it. Requires a matching resource block in configuration first.
Provider Version Problems
terraform init -upgradeRe-resolves provider versions against your version constraints, picking up newer releases within them.
Pin, don't chase
Pin provider versions with a required_providers block and a committed .terraform.lock.hcl. Most "it worked
yesterday" incidents are an unpinned provider picking up a breaking minor release.
Dependency and Ordering Failures
If apply fails partway through, Terraform's graph means some resources are created and others aren't — state now
reflects reality for what succeeded. Re-running apply is almost always correct: Terraform re-plans from the
current state and only acts on what's still needed. Resist the urge to manually edit state to "fix" a partial apply.
Never hand-edit the state file
Editing terraform.tfstate directly is unsupported and easy to get subtly wrong — a malformed field or a stale
serial number can make future applies mis-diff every resource in it. Use terraform state subcommands instead;
they update the file safely.