Pulumi Error: 'cannot delete resource because it still has dependencies' During Destroy
Fix Pulumi's 'cannot delete resource ... because it still has dependencies' error on destroy: understand dependency ordering, deleteBeforeReplace, and how to unblock a stuck teardown safely.
- #pulumi
- #iac
- #troubleshooting
- #errors
Stuck on this Pulumi error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Exact Error Message
Diagnostics:
aws:ec2:Vpc (main-vpc):
error: deleting urn:pulumi:prod::network::aws:ec2/vpc:Vpc::main-vpc:
[WARNING] Running "pulumi destroy" will delete resources that other
resources still depend on.
error: cannot delete resource
urn:pulumi:prod::network::aws:ec2/vpc:Vpc::main-vpc because it still
has dependencies:
- urn:pulumi:prod::network::aws:ec2/subnet:Subnet::app-subnet
- urn:pulumi:prod::network::aws:ec2/securityGroup:SecurityGroup::web-sg
error: update failed
You may also see this as resource ... cannot be deleted because it is protected when the dependency itself carries protect: true.
What It Means
Pulumi tracks a dependency graph between resources in the stack’s state (checkpoint). During pulumi destroy it deletes resources in reverse dependency order — children first, then parents. This error appears when Pulumi is asked to delete a resource that still has live dependents recorded in state, which would leave those dependents pointing at something that no longer exists.
Most often this is not a real cloud problem but a state/graph problem: a dependent was removed from the program without being removed from state, a protect flag is blocking a child, or an out-of-band change in the cloud provider left orphaned relationships. The teardown stops rather than risk corrupting the graph.
Common Causes
- A dependent resource is marked
protect: true, so Pulumi refuses to delete it, and that cascades to its parent. - Manual (out-of-band) changes in the cloud console created dependencies Pulumi does not know how to sequence.
- A resource was deleted from the program but still exists in state (a pending or half-applied change).
- A
deleteBeforeReplaceordering conflict during a replacement that touches a shared parent. - Provider-level dependencies (for example, an ENI or route table the provider attached automatically) that block the parent’s deletion.
Diagnostic Commands
Inspect the dependency graph recorded in state:
pulumi stack graph deps.dot
List every resource and its URN so you can see parent/child relationships:
pulumi stack --show-urns
Preview the destroy to see the exact ordering Pulumi intends, without executing it:
pulumi destroy --preview-only --diff
Check whether the blocking child is protected by exporting and searching the state:
pulumi stack export | jq '.deployment.resources[] | select(.protect == true) | .urn'
Step-by-Step Resolution
- Identify the specific dependents named in the error and confirm they exist in state:
pulumi stack --show-urns | grep -E 'app-subnet|web-sg'
- If a dependent is protected, remove protection before destroying. Do this per-resource rather than globally:
pulumi state unprotect 'urn:pulumi:prod::network::aws:ec2/subnet:Subnet::app-subnet'
- Re-run the destroy and let Pulumi sequence the deletions itself:
pulumi destroy
-
If a dependent lives in another stack (a
StackReferenceconsumer), destroy that dependent stack first. Pulumi cannot delete a resource another stack still references. -
If the dependency is an orphan left by an out-of-band change, delete just the stale child from state so the graph is consistent, then destroy:
pulumi state delete 'urn:pulumi:prod::network::aws:ec2/subnet:Subnet::app-subnet'
pulumi destroy
- As a last resort for a fully abandoned stack, target the parent explicitly after its children are gone:
pulumi destroy --target 'urn:pulumi:prod::network::aws:ec2/vpc:Vpc::main-vpc' --target-dependents
Prevention
- Reserve
protect: truefor genuinely irreplaceable resources, and script an unprotect step into your teardown runbooks. - Avoid making dependency-changing edits in the cloud console; let Pulumi own the graph.
- Destroy consumer stacks before the stacks that export shared infrastructure via
StackReference. - Run
pulumi destroy --preview-onlyin CI teardown jobs so ordering surprises appear before anything is deleted. - Keep
pulumi refreshcurrent so state reflects reality before you attempt a destroy.
Related Errors
resource ... cannot be deleted because it is protected— aprotectflag, not a dependency ordering issue.the stack has ... pending operations— an interrupted update left operations that must be cleared first.error: could not load plugin for provider— a missing provider plugin, unrelated to the graph.deleteBeforeReplacecycles — a replacement ordering conflict that can masquerade as a dependency error.
Frequently Asked Questions
Will pulumi state delete remove the resource from the cloud? No. It only removes the resource from Pulumi’s state; the cloud object is left as-is (orphaned). Use it only when the object is already gone or you will delete it manually.
Why does destroy fail when the dependent is in a different stack? Pulumi tracks cross-stack references and refuses to delete an export that another stack still consumes. Destroy the consumer stack first, then the producer.
Is --target-dependents safe to use? It is safe but blunt: it deletes the targeted resource and everything that depends on it. Preview with --preview-only first so you know the full blast radius.
How do I stop this from blocking every teardown? Keep protect minimal, run pulumi refresh before destroys, and prefer authoring dependencies in code so Pulumi always has an accurate graph. For repeatable teardown patterns, browse the prompt library.
Where can I find related teardown fixes? See the full Pulumi guides for more destroy and state-management troubleshooting.
Fixed it? Get 500 Pulumi & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.