How to fix Namespace stuck in Terminating state in Kubernetes

KubernetesINTERMEDIATEHIGHUpdated Dec 5, 2025ยท 243 views

A namespace is stuck in Terminating state because finalizers have not been removed by their responsible controllers. This blocks namespace deletion and often indicates crashed operators or stuck resources.

Quick fix

Fixes Namespace stuck in Terminating state

kubectl get namespace <namespace-name> -o json | jq '.metadata.finalizers'
  1. Identify what is blocking namespace deletion
  2. List all resources in the namespace
  3. Force delete stuck resources within the namespace
  4. Remove finalizers from stuck resources directly
kubernetes โ€” error
kubectl get namespace <namespace-name> -o json | jq '.metadata.finalizers'
Namespace stuck in Terminating state

What this error means

A Kubernetes namespace stuck in the Terminating state occurs when the namespace deletion process cannot complete because finalizers (metadata keys that guard resource deletion) have not been removed by their responsible controllers. When you delete a namespace, Kubernetes sets its phase to 'Terminating' and attempts to garbage collect all dependent resources and remove finalizers. If any finalizer remains in the namespace's metadata.finalizers field, the namespace will indefinitely remain in Terminating state. Finalizers are protection mechanisms that ensure controllers have time to clean up owned resources before deletion occurs. Common sources include CustomResource controllers, admission webhooks, and storage providers. When a controller dies, crashes, or malfunctions before removing its finalizer, or when a finalizer points to a resource that no longer exists, the namespace enters a permanent limbo state. This is particularly problematic because stuck namespaces consume cluster resources and make it impossible to fully remove abandoned projects or test environments.

Typical symptoms

  • kubectl delete namespace <name> completes but the namespace remains visible in kubectl get namespaces
  • kubectl describe namespace <name> shows phase=Terminating with no further progress
  • Applications cannot be deployed to a new namespace with the same name because the old one still exists
  • kubectl api-resources queries against the stuck namespace timeout or hang indefinitely
  • Monitoring systems report orphaned resources that cannot be accessed or deleted
  • Events in the stuck namespace show repeated failed attempts to delete specific resources

Common causes

  1. Finalizers from deleted or malfunctioning CustomResource controllers (operators) remain in resource metadata
  2. Storage finalizers from PersistentVolumeClaim or PersistentVolume resources that fail to clean up underlying storage
  3. Admission webhooks (ValidatingWebhookConfiguration or MutatingWebhookConfiguration) that block deletion requests
  4. Pods or other resources stuck in Terminating state with their own finalizers
  5. API server or etcd corruption where finalizer metadata is inconsistent
  6. Failed controller graceful shutdown where the controller was killed before it could remove finalizers
  7. Race conditions during cluster upgrades or mass resource deletions

How to fix "Namespace stuck in Terminating state"

1Identify what is blocking namespace deletion

Retrieve the namespace definition to see which finalizers are present:

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

Also check the namespace conditions:

bash
kubectl describe namespace <namespace-name>

This will show you exactly which finalizers are blocking deletion. Common finalizers include 'kubernetes' (built-in), controller finalizers like 'crd.projectcalico.org/finalizer', and storage finalizers.

2List all resources in the namespace

Use this comprehensive command to list ALL resources including CustomResources:

bash
kubectl api-resources --verbs=list --namespaced=true -o name | xargs -n 1 kubectl get --show-kind --ignore-not-found -n <namespace-name>

Note: 'kubectl get all' does NOT return CustomResources. Pay special attention to:
- PersistentVolumeClaims still bound to pods
- CustomResource instances from installed operators
- Any resources with Status.Conditions showing issues

3Force delete stuck resources within the namespace

For each stuck resource, delete it with grace-period=0:

bash
kubectl delete <resource-type> <resource-name> -n <namespace-name> --grace-period=0 --force --wait=false

For example, if a PVC is stuck:

bash
kubectl delete pvc my-stuck-pvc -n <namespace-name> --grace-period=0 --force

The --wait=false flag returns immediately. This may leave some cleanup incomplete, so only use after verifying resources are truly orphaned.

4Remove finalizers from stuck resources directly

If force delete doesn't work, patch the finalizers directly:

bash
kubectl patch <resource-type> <resource-name> -n <namespace-name> -p '{"metadata":{"finalizers":null}}' --type=merge

For a stuck PVC:

bash
kubectl patch pvc my-pvc -n <namespace-name> -p '{"metadata":{"finalizers":null}}'

After patching individual resources, they should delete immediately. Then attempt namespace deletion again:

bash
kubectl delete namespace <namespace-name>
5Clear finalizers from the namespace itself

If the namespace is still stuck, remove the namespace finalizers directly:

bash
kubectl patch namespace <namespace-name> -p '{"metadata":{"finalizers":null}}'

Or use the finalize endpoint directly:

bash
NAMESPACE=<namespace-name>
kubectl get namespace $NAMESPACE -o json | jq 'del(.spec.finalizers)' | kubectl replace --raw "/api/v1/namespaces/$NAMESPACE/finalize" -f -

This last method is the most reliable when other kubectl commands fail.

6Verify namespace deletion and check for orphaned resources

After clearing finalizers, verify the namespace is gone:

bash
kubectl get namespace <namespace-name>

You should see 'Error from server (NotFound)'. After successful deletion, check for orphaned resources:

bash
# Check for orphaned PVs
kubectl get pv | grep -i released

# Check for stuck pods cluster-wide
kubectl get pods --all-namespaces | grep Terminating

Manually clean up any remaining orphaned resources:

bash
kubectl patch pv <orphaned-pv-name> -p '{"metadata":{"finalizers":null}}'
kubectl delete pv <orphaned-pv-name> --grace-period=0 --force

Advanced notes

Finalizers are a critical Kubernetes mechanism. Every resource includes at least the 'kubernetes' finalizer, managed by the namespace lifecycle controller. When you delete a namespace, this controller waits for all child resources to be deleted and their finalizers removed before clearing its own finalizer.

Always investigate why finalizers exist before force-removing them. Understanding the cause helps prevent data loss. Use 'kubectl get <resource> -o yaml | grep -A 10 finalizers' on all resources.

Admission webhooks can block all deletions if misconfigured or pointing to unavailable services. List webhooks with: kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations and check their failurePolicy.

Third-party operators (Helm, ArgoCD, service mesh controllers) frequently add finalizers. Stuck namespaces often indicate operator pods crashed or the operator CRD was deleted without cleaning up instances. Check operator logs: kubectl logs -n <operator-namespace> deployment/<operator-name>

When dealing with CRD finalizers, deletion order matters. If a parent CRD deletes before children finish cleaning up, children become orphaned. Always delete leaf resources first, then parents.

After force-deleting a namespace with stuck finalizers, always check for orphaned resources (PVs still allocated, unused storage volumes, dangling load balancers). These won't automatically clean up and will continue consuming resources.

Frequently asked questions

What does "Namespace stuck in Terminating state" mean?
A Kubernetes namespace stuck in the Terminating state occurs when the namespace deletion process cannot complete because finalizers (metadata keys that guard resource deletion) have not been removed by their responsible controllers. When you delete a namespace, Kubernetes sets its phase to 'Terminating' and attempts to garbage collect all dependent resources and remove finalizers. finalizers field, the namespace will indefinitely remain in Terminating state.
How do I fix "Namespace stuck in Terminating state"?
A namespace is stuck in Terminating state because finalizers have not been removed by their responsible controllers. This blocks namespace deletion and often indicates crashed operators or stuck resources.
What causes "Namespace stuck in Terminating state"?
Finalizers from deleted or malfunctioning CustomResource controllers (operators) remain in resource metadata Storage finalizers from PersistentVolumeClaim or PersistentVolume resources that fail to clean up underlying storage Admission webhooks (ValidatingWebhookConfiguration or MutatingWebhookConfiguration) that block deletion requests
Is the "Namespace stuck in Terminating state" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading