Skip to main content
Fix Terraform Error: Destroy Dependency Violation

Fix Terraform Error: Destroy Dependency Violation

Key Takeaway

Fix terraform destroy dependency violation errors. Find dependent resources, destroy in correct order, use create_before_destroy, and handle stuck VPCs, security groups, and ENIs.

Table of Contents

Quick Answer

# Find what's blocking deletion
aws ec2 describe-network-interfaces \
  --filters "Name=group-id,Values=sg-0abc1234" \
  --query "NetworkInterfaces[].{ID:NetworkInterfaceId,Desc:Description}"

# Destroy in correct order
terraform destroy -target=aws_instance.web
terraform destroy

The Error

Error: deleting Security Group (sg-0abc1234):
DependencyViolation: resource sg-0abc1234 has a dependent object

Error: deleting VPC (vpc-0xyz5678):
DependencyViolation: The vpc 'vpc-0xyz5678' has dependencies and cannot be deleted.

Error: deleting Subnet (subnet-0def9012):
DependencyViolation: The subnet 'subnet-0def9012' has dependencies and cannot be deleted.

What Causes This

AWS won’t delete a resource that other resources depend on:

  • VPC can’t be deleted with subnets, security groups, or endpoints still in it
  • Security group can’t be deleted while attached to an EC2 instance, ENI, or RDS
  • Subnet can’t be deleted with running instances or ENIs
  • Out-of-band resources — something was created manually in the AWS console

Solution 1: Find Dependent Resources

Security Group Dependencies

# Find ENIs using this security group
aws ec2 describe-network-interfaces \
  --filters "Name=group-id,Values=sg-0abc1234" \
  --query "NetworkInterfaces[].{
    ID:NetworkInterfaceId,
    Type:InterfaceType,
    Description:Description,
    Status:Status,
    AZ:AvailabilityZone
  }" --output table

Common culprits:

  • Lambda ENIs (can take 20+ minutes to auto-delete)
  • ELB/ALB ENIs
  • ECS task ENIs
  • RDS interfaces

VPC Dependencies

# Find everything in the VPC
aws ec2 describe-instances --filters "Name=vpc-id,Values=vpc-0xyz5678" \
  --query "Reservations[].Instances[].{ID:InstanceId,State:State.Name}"

aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-0xyz5678" \
  --query "Subnets[].SubnetId"

aws ec2 describe-security-groups --filters "Name=vpc-id,Values=vpc-0xyz5678" \
  --query "SecurityGroups[].{ID:GroupId,Name:GroupName}"

aws ec2 describe-nat-gateways --filter "Name=vpc-id,Values=vpc-0xyz5678" \
  --query "NatGateways[].{ID:NatGatewayId,State:State}"

aws ec2 describe-vpc-endpoints --filters "Name=vpc-id,Values=vpc-0xyz5678" \
  --query "VpcEndpoints[].VpcEndpointId"

aws ec2 describe-internet-gateways \
  --filters "Name=attachment.vpc-id,Values=vpc-0xyz5678" \
  --query "InternetGateways[].InternetGatewayId"

Solution 2: Targeted Destroy (Inside Out)

Destroy child resources before parents:

# 1. Instances first
terraform destroy -target=aws_instance.web
terraform destroy -target=aws_instance.api

# 2. Then load balancers, NAT gateways
terraform destroy -target=aws_lb.main
terraform destroy -target=aws_nat_gateway.main

# 3. Then security groups, subnets
terraform destroy -target=aws_security_group.web

# 4. Then everything else
terraform destroy

Solution 3: create_before_destroy

For replacement (not destruction) — creates the new resource before deleting the old:

resource "aws_security_group" "web" {
  name_prefix = "web-sg-"
  vpc_id      = aws_vpc.main.id

  lifecycle {
    create_before_destroy = true
  }
}

Solution 4: Handle Lambda/ECS ENIs

Lambda and ECS create ENIs in your VPC that take 10-20 minutes to auto-delete after the function/service is destroyed:

# Check for lingering Lambda ENIs
aws ec2 describe-network-interfaces \
  --filters "Name=group-id,Values=sg-0abc1234" \
           "Name=status,Values=available" \
  --query "NetworkInterfaces[].NetworkInterfaceId"

# Delete available (detached) ENIs
aws ec2 delete-network-interface --network-interface-id eni-0abc1234

# Then retry
terraform destroy

Solution 5: force_destroy for S3

S3 buckets can’t be deleted if they contain objects:

resource "aws_s3_bucket" "logs" {
  bucket        = "my-logs-bucket"
  force_destroy = true   # Deletes all objects on destroy
}

Solution 6: Remove from State (Last Resort)

If the resource was deleted manually:

# Resource already gone from AWS but still in state
terraform state rm aws_security_group.old_sg

# Then destroy the rest
terraform destroy

Common Dependency Chains

VPC
├── Internet Gateway (detach before delete)
├── NAT Gateway (delete, wait for ENI cleanup)
├── Subnets
│   ├── EC2 Instances
│   ├── RDS Instances
│   ├── ECS Tasks (ENIs)
│   ├── Lambda (ENIs)
│   └── ALB/NLB
├── Security Groups (delete after all ENIs detached)
├── VPC Endpoints
└── Route Tables

Terraform usually handles this order correctly. The error happens when out-of-band resources exist or when ENIs are slow to delete.

Hands-On Courses

Conclusion

Dependency violations mean something else is using the resource you’re deleting. Find the dependent resource with AWS CLI, destroy children before parents using -target, and wait for Lambda/ECS ENIs to auto-delete (10-20 minutes). Use force_destroy = true on S3 buckets and create_before_destroy for security group replacements.

🚀

Level Up Your Terraform Skills

Hands-on courses, books, and resources from Luca Berton

Luca Berton
Written by

Luca Berton

DevOps Engineer, AWS Partner, Terraform expert, and author. Creator of Ansible Pilot, Terraform Pilot, and CopyPasteLearn.