🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

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.

Shubham4 min read
Share:Tweet

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

bash
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)

bash
# 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 table

A 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.

bash
# 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:

bash
aws elbv2 delete-load-balancer --load-balancer-arn arn:aws:elasticloadbalancing:...
terraform destroy    # Retry once the blocker is gone

Cause 2: Deletion Protection Enabled

bash
aws rds describe-db-instances --db-instance-identifier mydb \
  --query 'DBInstances[0].DeletionProtection'
# true    ← Terraform's destroy will fail here regardless of dependency graph correctness

Many 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:

hcl
resource "aws_db_instance" "main" {
  # ...
  deletion_protection = false    # Change this, apply, THEN destroy
}
bash
terraform apply    # Apply the protection change first
terraform destroy  # Then destroy will succeed

Cause 3: Resource Has an Implicit Dependent Terraform Doesn't Track

bash
# 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:

bash
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 too

Cause 4: Destroy Ordering Race — Cloud API Eventual Consistency

bash
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:

bash
sleep 30
terraform destroy

If 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

bash
terraform destroy
# Error: reading EC2 Security Group (sg-0abc123): InvalidGroup.NotFound

Ironically, 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:

bash
terraform state list | grep sg-0abc123
terraform state rm aws_security_group.orphaned
terraform destroy    # Retry, this resource is no longer in Terraform's plan

Diagnostic Approach for Any DependencyViolation

bash
# 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 once

More Terraform troubleshooting? Read our Terraform plan unexpected destroy fix and Terraform apply hangs fix.

Did this fix work?

Tell us what needs improving. No account required.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

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

Comments