helm/helm · critical

an error occurred while cleaning up resources. original roll

Error message

an error occurred while cleaning up resources. original rollback error: %w

What it means

Thrown by Rollback.performUpgrade when a rollback's Kubernetes Update() call already failed (release marked failed/superseded), the user enabled CleanupOnFail, and the follow-up attempt to delete the newly created resources (results.Created) also failed. It wraps the original rollback error as cause with the cleanup failure nested inside, so nothing is silently lost. It means the cluster is left in a partially rolled-back state that Helm cannot clean up automatically.

Source

Thrown at pkg/action/rollback.go:264

		current,
		target,
		kube.ClientUpdateOptionForceReplace(r.ForceReplace),
		kube.ClientUpdateOptionServerSideApply(serverSideApply, r.ForceConflicts),
		kube.ClientUpdateOptionThreeWayMergeForUnstructured(false),
		kube.ClientUpdateOptionUpgradeClientSideFieldManager(true))
	if err != nil {
		msg := fmt.Sprintf("Rollback %q failed: %s", targetRelease.Name, err)
		r.cfg.Logger().Warn(msg)
		currentRelease.Info.Status = common.StatusSuperseded
		targetRelease.Info.Status = common.StatusFailed
		targetRelease.Info.Description = msg
		r.cfg.recordRelease(currentRelease)
		r.cfg.recordRelease(targetRelease)
		if r.CleanupOnFail {
			r.cfg.Logger().Debug("cleanup on fail set, cleaning up resources", "count", len(results.Created))
			_, errs := r.cfg.KubeClient.Delete(results.Created, metav1.DeletePropagationBackground)
			if errs != nil {
				return targetRelease, fmt.Errorf(
					"an error occurred while cleaning up resources. original rollback error: %w",
					fmt.Errorf("unable to cleanup resources: %w", joinErrors(errs, ", ")))
			}
			r.cfg.Logger().Debug("resource cleanup complete")
		}
		return targetRelease, err
	}

	var waiter kube.Waiter
	if c, supportsOptions := r.cfg.KubeClient.(kube.InterfaceWaitOptions); supportsOptions {
		waiter, err = c.GetWaiterWithOptions(r.WaitStrategy, r.WaitOptions...)
	} else {
		waiter, err = r.cfg.KubeClient.GetWaiter(r.WaitStrategy)
	}
	if err != nil {
		return nil, fmt.Errorf("unable to get waiter: %w", err)
	}
	if r.WaitForJobs {

View on GitHub (pinned to 2a29f1770b)

Solutions

  1. Inspect the wrapped chain: the outer message names cleanup, the inner 'unable to cleanup resources' lists per-resource delete errors, and %w carries the original rollback error — fix that root cause first
  2. Manually delete the leftover created resources with kubectl (match what the rollback had just created; check release manifest and events)
  3. Verify RBAC: the identity needs delete on every resource kind the chart creates, not just create/update
  4. Retry the rollback after the root cause is fixed; check 'helm history' and 'kubectl get events' to confirm the failed/created set
  5. If a webhook/finalizer blocks deletes, remove the finalizer or exempt the rollback identity before retrying
Defensive patterns

Strategy: try-catch

Try / catch

res, err := rollback.RunWithContext(ctx, name)
if err != nil {
    if strings.Contains(err.Error(), "an error occurred while cleaning up resources") {
        // release marked failed in storage; cluster partially rolled back
        var cleanupInner *myJoinErr // unwrap chain: outer %w -> inner "unable to cleanup resources"
        if inner := errors.Unwrap(errors.Unwrap(err)); inner != nil {
            log.Printf("per-resource delete failures: %v", inner)
        }
        // audit created-but-not-deleted resources before retrying
    }
    return err
}

Prevention

When it happens

Trigger: helm rollback with --cleanup-on-fail where KubeClient.Update returns an error after creating some resources, and the subsequent KubeClient.Delete(results.Created, DeletePropagationBackground) returns at least one error. Programmatic equivalent: Rollback action with CleanupOnFail=true, a failing cluster update, then failing deletes (RBAC denial on delete, resource already being garbage-collected, API timeout).

Common situations: ServiceAccount lacks delete permissions but has create/update; cluster admission controllers (e.g. finalizer-adding webhooks) block deletion; network disruption to the API server mid-rollback; resources created with ownerReferences that propagate deletes unexpectedly; concurrent operator fighting the rollback.

Related errors


AI-assisted analysis of helm/helm@2a29f1770b (2026-08-15). Data as JSON: /api/errors/492a7e9a3c6aa6b5. Report an issue: GitHub.