Troubleshooting Failed and Stuck Releases
When a release is stuck pending-upgrade or an upgrade keeps failing, know how to read the real error, break the lock, and recover without nuking everything.
Sooner or later you meet a release stuck in pending-upgrade, or an upgrade that fails with a cryptic message. Panic-uninstalling loses history and can delete live resources. Here is the calm, senior recovery path.
Read the actual error first
The helm upgrade output truncates. Go to the source: helm status <release> shows the current phase, and kubectl describe / kubectl logs on the failing Pod or Job almost always reveal the real cause — an ImagePullBackOff, a failed migration hook, a missing Secret. Helm is usually the messenger, not the culprit.
The classic: stuck in pending-upgrade
If a helm upgrade is killed midway (CI runner dies, laptop closes), the release can be left in pending-upgrade and every retry refuses with "another operation is in progress." There is no operation — just a stale lock. Fix it by rolling back to the last deployed revision, which resets the status:
helm rollback <release> <last-good-revision>clears the stuck state and returns you to something known-good.- If even that refuses, the
helm mapkubeapisplugin repairs releases broken by removed Kubernetes APIs, and in the worst case you can delete the specificsh.helm.release.v1.<name>.v<n>Secret for the bad revision.
Other frequent offenders
- "field is immutable" — you changed a Deployment/StatefulSet selector or a Service's
clusterIP. These cannot be patched; the resource must be recreated. - Ownership conflicts — "invalid ownership metadata" means a resource already exists but was not created by this release. Label/annotate it for adoption, or remove it.
Prevention beats cure: --atomic from the previous lesson means most failed upgrades roll themselves back and never leave a stuck release for you to untangle.Example
# 1) Get the real story -- Helm status plus the failing Pod's events/logs
helm status my-web -n web
kubectl get pods -n web
kubectl describe pod -n web -l app.kubernetes.io/instance=my-web
kubectl logs -n web -l app.kubernetes.io/instance=my-web --tail=50
# 2) Release stuck in 'pending-upgrade'? Roll back to the last good revision
helm history my-web -n web # find the last DEPLOYED revision
helm rollback my-web 4 -n web --wait # clears the stale lock
# 3) Broken by removed Kubernetes APIs after a cluster upgrade
helm plugin install https://github.com/helm/helm-mapkubeapis
helm mapkubeapis my-web -n webWhen to use it
- An SRE encounters a release stuck in pending-upgrade and uses helm rollback to break the stuck state before attempting the upgrade again with a corrected values file.
- A developer investigates a failed install by running helm get manifest to see which resources were applied and kubectl describe to read the events on the failing Pod.
- A platform engineer uses helm history and kubectl get events to correlate a bad upgrade with a specific chart version and Kubernetes event timestamp, then rolls back.
More examples
Unstick a pending-upgrade release
Rolls back a release stuck in pending-upgrade, which resets its state to deployed and allows subsequent upgrade attempts.
# Release is stuck in pending-upgrade state
helm list --all -n production | grep pending
# Roll back to break the stuck state
helm rollback my-app -n production
# Verify release is now deployed
helm list -n productionDiagnose a failed install
Uses three commands to diagnose a failed install: Helm status for high-level info, get manifest to see what was applied, and events for root-cause signals.
# Check Helm release status
helm status my-app -n staging
# See the rendered manifests that were applied
helm get manifest my-app -n staging
# Check Kubernetes events for the namespace
kubectl get events -n staging --sort-by='.lastTimestamp' | tail -20Force replace a stuck resource
Uses --force to delete and re-create resources that are stuck in a terminal state, or manually deletes a specific stuck resource so Helm can recreate it.
# When a resource is stuck and normal upgrade cannot proceed:
helm upgrade my-app ./myapp \
-f values-prod.yaml \
--force \
-n production
# Or delete the specific stuck resource and let Helm re-create it:
kubectl delete pod my-app-migration-xyz -n production
Discussion