🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Helm Rollback Failed: Fix in 5 Minutes

helm rollback failing with 'another operation is in progress' or leaving the release in a broken state? Here is exactly how to diagnose stuck release secrets, failed hooks, and resource conflicts blocking a Helm rollback.

Shubham4 min read
Share:Tweet

A failed rollback is worse than a failed upgrade — you're trying to get back to a known-good state and even that is blocked. Here is how to diagnose the real cause instead of repeatedly retrying the same rollback command.

Step 1: Check the Release's Actual State

bash
helm status myapp -n production
# STATUS: pending-upgrade    ← this blocks new operations, including rollback
 
helm history myapp -n production
# REVISION  STATUS      DESCRIPTION
# 12        deployed    Upgrade complete
# 13        failed      Upgrade "myapp" failed: timed out waiting for condition
# 14        pending-upgrade    ← stuck here from a previous failed rollback attempt

If the release is stuck in pending-upgrade or pending-rollback, Helm refuses any new operation on it — this is the most common blocker.

Cause 1: Release Stuck in pending-upgrade/pending-rollback (Most Common)

bash
helm rollback myapp 12 -n production
# Error: UPGRADE FAILED: another operation (install/upgrade/rollback) is in progress

This happens when a previous helm upgrade or rollback was interrupted (network drop, CI job killed, Ctrl+C) — Helm's release secret still shows the operation as in-progress even though nothing is actually running.

bash
# Confirm nothing is actually running against this release
kubectl get pods -n production -l app.kubernetes.io/managed-by=Helm

Fix — Helm 3.11+ has a direct command for this:

bash
helm rollback myapp 12 -n production --force    # Sometimes bypasses the lock; try this first
 
# If that doesn't work, manually patch the release secret's status
kubectl get secrets -n production -l owner=helm,name=myapp --sort-by=.metadata.creationTimestamp
# Find the most recent one, decode and check its status
kubectl get secret sh.helm.release.v1.myapp.v14 -n production -o jsonpath='{.data.release}' | base64 -d | base64 -d | gunzip
bash
# If confirmed stuck (no operation actually running), the safest fix is
# deleting the stuck revision's secret so Helm no longer sees it as in-progress
kubectl delete secret sh.helm.release.v1.myapp.v14 -n production
helm rollback myapp 12 -n production

Only delete the release secret after confirming via kubectl get pods and recent events that nothing is genuinely mid-operation — deleting it while something is actually running creates a worse state mismatch.

Cause 2: PreRollback/PostRollback Hook Failing

bash
kubectl get jobs -n production -l helm.sh/hook
# NAME                  COMPLETIONS   AGE
# myapp-pre-rollback     0/1           5m    ← stuck or failed
bash
kubectl logs job/myapp-pre-rollback -n production

Fix — resolve the underlying hook failure, then clean up and retry:

bash
kubectl delete job myapp-pre-rollback -n production
helm rollback myapp 12 -n production

If the hook consistently fails for a reason unrelated to the rollback itself (e.g., a migration script erroring), you may need --no-hooks as a last resort to get the release state consistent, then handle the hook's concern manually:

bash
helm rollback myapp 12 -n production --no-hooks

Cause 3: Target Revision's Resources Conflict With Current Cluster State

bash
helm rollback myapp 12 -n production
# Error: rollback "myapp" failed: cannot patch "myapp" with kind Deployment:
# spec.selector: Invalid value: ... field is immutable

If revision 12's manifest has a different spec.selector than what's currently deployed (common after someone manually edited a resource or a different chart version changed selector labels), Kubernetes rejects the patch — selectors are immutable on Deployments.

Fix — this needs a recreate, not a patch, for that specific resource:

bash
kubectl delete deployment myapp -n production --cascade=orphan    # Keeps pods running briefly
helm rollback myapp 12 -n production

--cascade=orphan avoids a hard outage during the delete — the pods keep running under the old ReplicaSet while Helm recreates the Deployment with the correct selector from revision 12.

Cause 4: Target Revision No Longer in History (Pruned)

bash
helm history myapp -n production
# Only shows the last 10 revisions by default — if you're trying to roll
# back further than that, it's already gone
helm rollback myapp 5 -n production
# Error: release: not found

Fix — check your history retention and, if the revision is gone, reconstruct manually from a backed-up values file or git-stored chart version:

bash
helm history myapp -n production --max 50    # Check actual available range
 
# If you know the exact chart version and values used previously (from Git history)
helm upgrade myapp ./chart --version 2.3.0 -f old-values.yaml -n production

Increase history retention going forward so this doesn't happen again:

bash
helm upgrade myapp ./chart --history-max 20 -n production

Diagnostic Checklist

bash
helm status myapp -n production                                  # current release state
helm history myapp -n production                                  # available rollback targets
kubectl get jobs -n production -l helm.sh/hook                    # stuck hooks
kubectl get secrets -n production -l owner=helm,name=myapp        # release secret states
kubectl get events -n production --sort-by='.lastTimestamp' | tail -20

More Helm troubleshooting? Read our Helm upgrade failed another operation in progress fix and Helm values not updating fix.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments