How to fix Error: Instance cannot be destroyed - resource has lifecycle.prevent_destroy set in Terraform

TerraformINTERMEDIATEHIGHUpdated Dec 30, 2025ยท 144 views

The prevent_destroy lifecycle argument protects critical resources from accidental deletion. When enabled, Terraform blocks any destroy operations. To proceed, you must either remove the protect_destroy setting, delete the resource from configuration, or remove it from Terraform state.

Quick fix

Fixes Error: Instance cannot be destroyed - resource has lifecycle.prevent_destroy set

# Look for this pattern in your Terraform configuration
resource "aws_instance" "example" {
  # ... configuration ...

  lifecycle {
    prevent_destroy = true
  }
}
  1. Verify the prevent_destroy setting
  2. Disable prevent_destroy if you want to destroy the resource
  3. Alternatively: Remove resource from state without destroying
  4. Handle prevent_destroy in nested modules
terraform โ€” error
# Look for this pattern in your Terraform configuration
resource "aws_instance" "example" {
# ... configuration ...
lifecycle {
prevent_destroy = true
}
}
Error: Instance cannot be destroyed - resource has lifecycle.prevent_destroy set

What this error means

Terraform's lifecycle.prevent_destroy is a safeguard that prevents resources from being destroyed as part of a terraform destroy or terraform apply operation. When this protection is enabled and Terraform attempts to destroy the resource, it will fail with an error. This is intentional protection for critical resources like production databases, storage buckets with important data, or compliance-sensitive assets. However, it creates a deliberate blocker when you actually need to destroy the resource. The error occurs because Terraform evaluates the prevent_destroy setting early in its planning phase, before any execution. This means the protection applies regardless of whether you're intentionally destroying the resource or accidentally did so by removing its configuration.

Typical symptoms

  • terraform apply fails when trying to destroy a protected resource
  • terraform destroy command fails on resources with prevent_destroy = true
  • Plan shows resource would be destroyed, but apply is blocked
  • Error message appears during terraform plan when resource is marked for destruction

Common causes

  1. Resource has lifecycle.prevent_destroy = true explicitly configured
  2. Removing the resource block from Terraform configuration triggers the protect mechanism
  3. Attempting to run terraform destroy when protected resources exist
  4. Nested modules contain protected resources and you're trying to destroy the parent module

How to fix "Error: Instance cannot be destroyed - resource has lifecycle.prevent_destroy set"

1Verify the prevent_destroy setting

First, identify which resource has prevent_destroy enabled and confirm it's actually set to true.

hcl
# Look for this pattern in your Terraform configuration
resource "aws_instance" "example" {
  # ... configuration ...

  lifecycle {
    prevent_destroy = true
  }
}

If you see this in your code, this is the cause. Note the resource type and name for the next steps.

2Disable prevent_destroy if you want to destroy the resource

If you genuinely want to destroy this resource, set prevent_destroy to false or remove the lifecycle block entirely.

hcl
# Option 1: Change to false
resource "aws_instance" "example" {
  # ... configuration ...

  lifecycle {
    prevent_destroy = false
  }
}

# Option 2: Remove the lifecycle block entirely
resource "aws_instance" "example" {
  # ... configuration ...
}

After making this change, run terraform plan to verify the change is recognized:

bash
terraform plan

Then you can proceed with destroy:

bash
terraform apply  # Apply the plan that now allows destruction
terraform destroy  # Or destroy specific resource
3Alternatively: Remove resource from state without destroying

If you want to unmanage the resource (stop Terraform from tracking it) without actually destroying it in your cloud provider, use terraform state rm:

bash
terraform state rm aws_instance.example

This removes the resource from Terraform's state file, but the actual infrastructure remains running in AWS (or your provider). This is useful when:
- You want to manage the resource outside of Terraform
- You're migrating the resource to a different Terraform configuration
- You want to keep the resource but stop protecting it

Verify the resource was removed from state:

bash
terraform state list | grep example

The resource should no longer appear in the state.

4Handle prevent_destroy in nested modules

If the protected resource is in a nested module and you cannot edit the module directly, you have limited options:

1. Request the module owner/maintainer to add a variable to make prevent_destroy configurable:

hcl
variable "prevent_destroy" {
  type    = bool
  default = true
}

lifecycle {
  prevent_destroy = var.prevent_destroy
}

2. Fork/copy the module and customize it for your use case

3. Use terraform state rm to remove the module's resources from state before destroying the parent module:

bash
terraform state rm 'module.my_module.aws_instance.example'

4. As a last resort, manually delete the infrastructure outside Terraform, then clean up state:

bash
# Manually delete in cloud console, then
terraform state rm <resource_address>

Advanced notes

Understanding prevent_destroy Behavior:

prevent_destroy only blocks destruction when the resource block remains in configuration. If you remove the resource block entirely from your .tf files, Terraform will allow destruction because the lifecycle rule is removed along with the resource definition. This is a common gotcha when managing resources.

When prevent_destroy Should Be Used:
- Production databases with critical data
- S3 buckets storing important backups or archives
- RDS instances serving live applications
- Compliance-critical assets subject to regulations
- Any stateful infrastructure that cannot be easily replaced

Alternative Approaches to Prevent Accidental Destruction:
1. Use Terraform Cloud with mandatory approval policies for destroy operations
2. Implement Cost Estimation gates that flag destruction of expensive resources
3. Use separate Terraform workspaces for production to add a layer of separation
4. Implement a tag-based policy in your cloud provider to block deletion of tagged resources
5. Use terraform lock files and code review processes to prevent sneaky removals

Removing prevent_destroy vs. Removing Resource from State:
- Set prevent_destroy = false then destroy: Completely removes the resource from your cloud provider
- terraform state rm: Removes Terraform tracking but leaves the actual infrastructure running in the cloud
- Choose based on whether you want the cloud resources to exist after being unmanaged

Frequently asked questions

What does "Error: Instance cannot be destroyed - resource has lifecycle.prevent_d" mean?
prevent_destroy is a safeguard that prevents resources from being destroyed as part of a terraform destroy or terraform apply operation. When this protection is enabled and Terraform attempts to destroy the resource, it will fail with an error. This is intentional protection for critical resources like production databases, storage buckets with important data, or compliance-sensitive assets.
How do I fix "Error: Instance cannot be destroyed - resource has lifecycle.prevent_d"?
The prevent_destroy lifecycle argument protects critical resources from accidental deletion. When enabled, Terraform blocks any destroy operations. To proceed, you must either remove the protect_destroy setting, delete the resource from configuration, or remove it from Terraform state.
What causes "Error: Instance cannot be destroyed - resource has lifecycle.prevent_d"?
Resource has lifecycle.prevent_destroy = true explicitly configured Removing the resource block from Terraform configuration triggers the protect mechanism Attempting to run terraform destroy when protected resources exist
Is the "Error: Instance cannot be destroyed - resource has lifecycle.prevent_d" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading