skip to content

How do you clear a Helm release stuck in the uninstalling status?

level: seniorimportance: nice to knowfreq 22%

answer

  1. The delete path, not the write path
  2. No rollback rung exists here
  3. Something may still refuse to be deleted
  4. Records last, survivors first
  5. Some resources were never going to be removed

basics

~10 s

Find the object whose deletion never completed and unblock it, then re-run helm uninstall. Removing the release records first only hides the release: whatever is still running is orphaned with no owner on record.

solid answer

~40 s

`uninstalling` is written when `helm uninstall` starts deleting a release's resources and never reaches the terminal `uninstalled` state. The usual cause is a deletion that blocks — an object whose finalizers never clear, an admission webhook rejecting the delete, or a pre-delete hook that never finishes — or a client killed part-way, exactly as with the pending statuses. Unlike `pending-upgrade`, there is no rollback rung: you cannot roll forward out of a half-deleted release. Work it in this order: list the release's objects and find the one still terminating, remove whatever is holding it, re-run `helm uninstall`. Only when the release must go and the objects are already gone do you delete the release records by hand — and accept that any survivors become orphans a later install will refuse to overwrite.

code

bash · 8 lines
bash
helm status billing-cron -n billing
helm get manifest billing-cron -n billing

# Anything already marked for deletion is where the uninstall is wedged
kubectl get all -n billing -l app.kubernetes.io/instance=billing-cron

# Once the blockage is cleared, let Helm finish its own sequence
helm uninstall billing-cron -n billing

go deeper

for a junior

Recall that this status means an uninstall started and never finished, and that the first move is to look at what is still running rather than to delete Helm's own records.

for a middle

Explain the uninstall sequence — mark, delete in reverse order, record the terminal status — and name the two families of cause: a client that died, and a deletion the cluster would not complete.

for a senior

Demonstrate the inverted ladder: no rollback exists, so you unblock the deletion and let Helm finish, and you treat record deletion as the move that manufactures orphans. Separate deliberately retained resources from genuinely stuck ones.

for a principal

Frame it as a blast-radius question: a webhook or operator that blocks deletes wedges uninstalls cluster-wide, so the durable fix is failure-mode policy for those components rather than a runbook for clearing one release.

## Where the status comes from `helm uninstall` is not a single API call. Helm reads the release's stored manifest, marks the release `uninstalling`, deletes the objects in the reverse of its install order, runs any delete hooks, and finally records the release as `uninstalled` — or removes its records entirely, depending on whether history is being kept. A release you find sitting in `uninstalling` stopped somewhere in the middle of that. There are two families of cause, and telling them apart is the whole diagnosis. **The client died.** Same story as the pending statuses: the job was cancelled, the runner evicted, the connection dropped. Helm wrote its intent and never came back to write the outcome. Nothing in the cluster is wedged; the record is just stale. **A deletion blocked.** Helm issued the delete, the API server accepted it, and the object did not actually go away. The usual reasons are an object whose finalizers are never cleared because the controller that owns them is gone or failing, an admission webhook that rejects deletes (or whose backing service is unreachable, so the delete cannot be admitted at all), or a `pre-delete` hook that hangs and never completes. Here something in the cluster genuinely needs attention, and clearing the release record would leave that thing behind. ## Why the recovery ladder is different For a release in `pending-upgrade` the friendly rung is a rollback: there is an earlier revision that reached `deployed`, and Helm can replay its manifest. A half-uninstalled release has no such rung. You cannot roll a deletion forward, and rolling back to a revision whose objects have been partly deleted is not a recovery — it is a reinstall wearing a rollback's name, and it will collide with whichever objects survived. So the order of operations is: 1. **Inventory what is left.** The release's stored manifest tells you what should have gone. Compare it with what is still in the namespace, and note anything with a deletion timestamp already set — those are the objects the deletion is stuck on rather than objects that were never reached. 2. **Unblock the deletion.** Fix what is holding it: bring back the controller that clears the finalizers, repair or remove the failing admission webhook, or deal with the hook that never finished. Once the object can actually be deleted, it will be. 3. **Re-run `helm uninstall`.** With the blockage gone, Helm can complete the sequence and write a terminal status. 4. **Only then consider the records.** If the release must disappear and the objects are genuinely already gone, deleting the release records is the last lever. ## What deleting the records costs Helm's knowledge of a release is entirely in its records. Delete them and the release stops existing as far as Helm is concerned — it will not be listed, it has no history, and no `helm` command can act on it. Anything that survived the partial uninstall is now an orphan: it is still running, it still carries the ownership metadata naming the release it belonged to, and the next `helm install` that renders the same object is rejected because that object already exists and belongs to a release Helm cannot see. You have swapped a visible stuck release for invisible debris, which is strictly worse for the next person. Clean up the survivors yourself before, or immediately after, you remove the records. One related trap: resources annotated to be kept on deletion, and CRDs installed from a chart's `crds/` directory, are deliberately never removed by an uninstall at all. If those are the objects you find still standing, the release is not stuck on them — they were always going to survive, and the release's `uninstalling` status has some other cause. Confusing "deliberately retained" with "failed to delete" sends the whole diagnosis in the wrong direction. ## Prevention Most stuck uninstalls trace back to something else being broken: a dead operator whose finalizers nobody can clear, or a webhook whose backing service went away while its configuration stayed. Both are worth treating as their own reliability problems — a webhook that fails closed on deletes can wedge every uninstall in the cluster, not just this one. And as with the pending statuses, give delete jobs enough budget to finish rather than cancelling them, because a client that survives long enough to write a terminal status leaves you nothing to repair.

  • Why is there no rollback rung for a release stuck in uninstalling, when pending-upgrade has one?
    Rollback replays the stored manifest of an earlier revision, which assumes the release still exists as a coherent set of objects. A half-deleted release does not: some objects are gone, some survive, some are mid-deletion. Replaying an old manifest over that is a reinstall that collides with the survivors rather than a recovery. The only forward path is to finish the deletion that was started.
  • You find objects from the release still running after the uninstall wedged. How do you tell which ones are the blockage?
    The ones already marked for deletion but still present are where the uninstall is stuck — the delete was accepted and something is preventing completion. Objects with no deletion mark are simply ones Helm never reached. And separately, resources annotated to be kept, plus CRDs installed from the chart's crds/ directory, were never going to be deleted at all, so their presence proves nothing.

saying these in an interview costs you the question

  • Deleting the release records before the objects
  • Trying to roll back out of a half-completed uninstall
  • Assuming surviving objects mean Helm failed to delete them
  • Believing CRDs from crds/ are removed by uninstall
  • Ignoring a failing admission webhook that blocks deletes

context