Skip to content
Error: cannot delete resource

Error: cannot delete resource

DodaTech 3 min read

The “cannot delete resource” error means Kubernetes refused deletion because the resource has finalizers or dependencies, leaving it stuck in Terminating.

What It Means

When you run kubectl delete, Kubernetes sets a deletionTimestamp on the resource but doesn’t remove it immediately. Finalizers are hooks that must complete before deletion. If a finalizer cannot finish — or if there’s a protection mechanism — the resource stays in a Terminating state.

Why It Happens

  • The resource has finalizers that block deletion (common with custom resources).
  • A namespace is stuck in Terminating because of outstanding resources.
  • The resource is being used by another resource (e.g. a PVC used by a pod).
  • Termination protection is enabled on the resource (cloud-specific).
  • The resource controller is not running and can’t process the finalizer.
  • A finalizer references a resource that no longer exists.
  • The resource has owner references preventing deletion of dependents.

How to Fix It

Step 1: Check the resource for finalizers

kubectl get <resource> <name> -o json | jq '.metadata.finalizers'

If the output shows finalizers like kubernetes.io/pv-protection or foregroundDeletion, these are blocking deletion.

Step 2: Remove finalizers

To remove all finalizers and force deletion:

kubectl patch <resource> <name> -p '{"metadata":{"finalizers":[]}}' --type=merge

For namespaces stuck in Terminating:

kubectl get namespace <stuck-namespace> -o json | jq '.spec = {"finalizers":[]}' > tmp.json
kubectl proxy &
curl -k -H "Content-Type: application/json" -X PUT --data-binary @tmp.json http://localhost:8001/api/v1/namespaces/<stuck-namespace>/finalize

Step 3: Delete dependent resources first

If the resource is being used, delete the dependents beforehand:

# PVC that is mounted by a pod
kubectl delete pod <pod-name>
kubectl delete pvc <pvc-name>

# Service that backs a deployment
kubectl delete deployment <deployment-name>
kubectl delete service <service-name>

Step 4: Use force delete

For pods stuck in Terminating:

kubectl delete pod <pod-name> --force --grace-period=0

This bypasses the graceful shutdown period and immediately removes the pod from the API server. Use with caution — running containers may be orphaned.

Step 5: Disable termination protection (cloud resources)

For resources behind a load balancer or with termination protection:

# AWS ELB / ALB
aws elb delete-load-balancer --load-balancer-name <name>
aws elbv2 delete-load-balancer --load-balancer-arn <arn>

# Then remove the Kubernetes service
kubectl delete service <service-name>

Step 6: Check ownerReferences

kubectl get <resource> <name> -o json | jq '.metadata.ownerReferences'

If the resource has an owner that no longer exists, the garbage collector may be stuck. Remove the ownerReference:

kubectl patch <resource> <name> -p '{"metadata":{"ownerReferences":[]}}' --type=merge
What are finalizers in Kubernetes?
Finalizers are keys on a resource that must be processed before the resource can be deleted. They act like pre-delete hooks. Controllers watch for deletion timestamps and run cleanup logic. If a controller is missing or misconfigured, the finalizer never completes and the resource stays in Terminating forever.
Is --force --grace-period=0 safe for production?
It’s safe when you understand the consequences. Force-deleting a pod bypasses the kubelet’s termination process — containers continue running on the node until the kubelet detects the orphan and cleans up. This is acceptable for stuck resources but should not be the default deletion method.
How do I delete a namespace stuck in Terminating?
First find what’s blocking it: kubectl get namespace <name> -o json | jq '.spec.finalizers'. Then remove the finalizers using the API directly as shown in Step 2. This is the most reliable method. Avoid using kubectl delete namespace --force — it doesn’t work as expected.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro