Terraform Destroy Stuck on Dependency Violation: Fix in 5 Minutes
terraform destroy failing with 'DependencyViolation' or hanging on a resource that refuses to delete? Here is exactly how to diagnose orphaned dependencies, out-of-band changes, and deletion protection blocking a clean destroy.
DependencyViolation errors happen because cloud providers enforce their own deletion ordering rules independently of what Terraform's dependency graph thinks it knows — usually because something was created outside Terraform, or a resource has a dependent that Terraform's state doesn't track.
Step 1: Read the Exact Error
terraform destroy
# Error: deleting EC2 VPC (vpc-0abc123): DependencyViolation: The vpc
# 'vpc-0abc123' has dependencies and cannot be deleted.AWS (or your cloud provider) is telling you the VPC still has something attached to it — Terraform's state doesn't necessarily know what, because the blocking resource might not be in Terraform's state at all.
Cause 1: A Resource Was Created Outside Terraform (Most Common)
# Find everything actually inside the VPC, not just what Terraform manages
aws ec2 describe-network-interfaces --filters "Name=vpc-id,Values=vpc-0abc123" \
--query 'NetworkInterfaces[*].[NetworkInterfaceId,Description,Status]' --output tableA manually-created ENI, a Lambda function with VPC config, or a load balancer created via the console (not Terraform) will block VPC deletion, and Terraform has no way to know about it or clean it up — it's not in the state file.
# Common culprits: manually created security groups, an RDS instance
# someone spun up via console, a NAT gateway created outside Terraform
aws ec2 describe-security-groups --filters "Name=vpc-id,Values=vpc-0abc123"
aws elbv2 describe-load-balancers --query "LoadBalancers[?VpcId=='vpc-0abc123']"Fix — manually delete the out-of-band resource, then retry destroy:
aws elbv2 delete-load-balancer --load-balancer-arn arn:aws:elasticloadbalancing:...
terraform destroy # Retry once the blocker is goneCause 2: Deletion Protection Enabled
aws rds describe-db-instances --db-instance-identifier mydb \
--query 'DBInstances[0].DeletionProtection'
# true ← Terraform's destroy will fail here regardless of dependency graph correctnessMany resources (RDS instances, certain ALBs, some newer AWS resource types) support a deletion protection flag that blocks deletion at the API level, independent of Terraform entirely.
Fix — disable protection first, either via Terraform config change + apply, or directly:
resource "aws_db_instance" "main" {
# ...
deletion_protection = false # Change this, apply, THEN destroy
}terraform apply # Apply the protection change first
terraform destroy # Then destroy will succeedCause 3: Resource Has an Implicit Dependent Terraform Doesn't Track
# terraform state doesn't automatically know about implicit
# infrastructure relationships some providers create behind the scenes
terraform state list | grep vpc
# Shows the VPC and explicitly-managed subnets, but maybe not
# a NAT gateway's elastic IP association, VPC peering connections, etc.Fix — import the untracked dependent resource into state so Terraform can manage its deletion too:
aws ec2 describe-vpc-peering-connections --filters "Name=requester-vpc-info.vpc-id,Values=vpc-0abc123"
terraform import aws_vpc_peering_connection.orphaned pcx-0xyz789
terraform destroy # Now Terraform knows to remove this tooCause 4: Destroy Ordering Race — Cloud API Eventual Consistency
terraform destroy
# Error: DependencyViolation ... (on a resource that SHOULD already be gone
# based on the plan output)Some cloud APIs have eventual consistency delays — a security group deletion can report success while the underlying network interface detachment hasn't fully propagated yet, causing the next dependent deletion to fail transiently.
Fix — simply retry after a short wait; this is often not a real blocker, just a timing issue:
sleep 30
terraform destroyIf it fails the same way repeatedly (not just once), it's not a timing issue — go back to Cause 1 or 3.
Cause 5: Terraform State Has a Stale Reference to an Already-Deleted Resource
terraform destroy
# Error: reading EC2 Security Group (sg-0abc123): InvalidGroup.NotFoundIronically, destroy can also fail because state references something that's already gone (deleted manually, or by a previous partial destroy).
Fix — remove the stale reference from state so Terraform stops trying to manage something that no longer exists:
terraform state list | grep sg-0abc123
terraform state rm aws_security_group.orphaned
terraform destroy # Retry, this resource is no longer in Terraform's planDiagnostic Approach for Any DependencyViolation
# 1. Identify what the cloud provider says is blocking deletion (from the error)
# 2. Check if that specific thing is in Terraform's state
terraform state list | grep <resource-hint>
# 3. If NOT in state — it was created out-of-band, delete manually or import it
# 4. If IN state but destroy still fails — check for deletion protection flags
# 5. If nothing obvious — check for eventual-consistency timing, retry onceMore Terraform troubleshooting? Read our Terraform plan unexpected destroy fix and Terraform apply hangs fix.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
Terraform Backend S3 Init Failed — Every Cause and Fix (2026)
terraform init fails with S3 backend errors — access denied, bucket does not exist, state lock issues, wrong region. Here's every cause and the exact fix for each one.
Terraform Import: Fixing State Conflicts with Existing Resources
Getting state conflicts or duplicate resource errors with terraform import? Learn how to import existing AWS resources, fix config mismatches, and use moved blocks to rename state entries.
Terraform Import Existing Resources: Fix State Mismatch and Drift
Existing AWS resources not in Terraform state? Use terraform import to bring them under management, fix state drift, and avoid accidental resource deletion — with exact commands for EC2, RDS, S3, VPC, and EKS.