SECURITY WARNING: Never run commands you don't understand. Always review code before execution. Use at your own risk.
Terraform New Added 8 September 2026

Terraform: Instance cannot be destroyed (prevent_destroy)

The resource carries a lifecycle block with prevent_destroy set, and the plan would destroy it. Terraform refuses at plan time, deliberately, because destroy is frequently implied by a change to an immutable attribute rather than requested outright.

Quick fix

Read the commands before running them. Anything that restarts a service, deletes data or changes permissions should be tried on a non-production system first.

Quick fix
# First find out why a destroy is planned at all
terraform plan -out=tfplan
terraform show -json tfplan | jq '.resource_changes[]
  | select(.change.actions[] | contains("delete"))
  | {addr: .address, why: .change.replace_paths}'

# Often an immutable field changed and a replace is implied.
# Change it back, or move the resource out of Terraform's control:
terraform state rm aws_db_instance.main

# Only remove the guard when the destroy is genuinely intended
lifecycle { prevent_destroy = false }   # then plan again

How to diagnose Terraform errors

Terraform errors are mostly state errors. A stuck lock, a resource that exists in the cloud but not in state, or a value that cannot be known until apply time all trace back to how Terraform models the world. The for_each-on-unknown-values error is the most common conceptual stumble: Terraform must know the keys of a map at plan time, even if the values are unknown.

If the quick fix above does not resolve it, work through these steps. They apply to this whole class of error, not just to this one message, which is usually what saves the time.

  1. For a stuck lock, find out who holds it before forcing anything. terraform force-unlock <id> is safe only when you are certain no apply is running.
  2. Use terraform state list and terraform state show <addr> to see what Terraform believes exists, and terraform import to adopt resources created outside it.
  3. Set TF_LOG=DEBUG and TF_LOG_PATH=tf.log for provider-level detail on authentication and API errors.
  4. For for_each errors, restructure so keys come from static values or from variables, not from attributes of resources that do not yet exist. Use -target for a staged apply as a last resort.
  5. Run terraform plan -refresh-only to see drift explicitly before applying anything unexpected.

Tools worth reaching for

  • terraform state list/show
  • TF_LOG=DEBUG
  • terraform plan -refresh-only
  • terraform graph
  • tflint / checkov

Authoritative references

Primary documentation for this error, worth reading before applying any fix in production.

developer.hashicorp.com

Related Terraform errors

See all 18 Terraform errors →

Browse other categories

Something missing or wrong?

This entry is maintained by hand. If the fix is out of date, incomplete, or you have a better one, email a correction and it will be reviewed.