🎉 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.

Did this fix work?

Tell us what needs improving. No account required.

🔧

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