helm/helm · error

pre-upgrade hooks failed: %w

Error message

pre-upgrade hooks failed: %w

What it means

releasingUpgrade runs pre-upgrade hooks (annotation helm.sh/hook: pre-upgrade) via cfg.execHook before any release resource is applied (pkg/action/upgrade.go:457-462). This error means at least one hook failed: the hook Job/Pod exited non-zero, could not be created, or its wait exceeded the timeout. No release resources have been touched yet when this fires.

Source

Thrown at pkg/action/upgrade.go:461

		err := ctx.Err()

		// when RollbackOnFailure is set, the ongoing release finish first and doesn't give time for the rollback happens.
		u.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, err)
	case <-done:
		return
	}
}

func isReleaseApplyMethodClientSideApply(applyMethod string) bool {
	return applyMethod == "" || applyMethod == string(release.ApplyMethodClientSideApply)
}

func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *release.Release, current kube.ResourceList, target kube.ResourceList, originalRelease *release.Release, serverSideApply bool) {
	// pre-upgrade hooks

	if !u.DisableHooks {
		if err := u.cfg.execHook(upgradedRelease, release.HookPreUpgrade, u.WaitStrategy, u.WaitOptions, u.Timeout, serverSideApply); err != nil {
			u.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, fmt.Errorf("pre-upgrade hooks failed: %w", err))
			return
		}
	} else {
		u.cfg.Logger().Debug("upgrade hooks disabled", "name", upgradedRelease.Name)
	}

	upgradeClientSideFieldManager := isReleaseApplyMethodClientSideApply(originalRelease.ApplyMethod) && serverSideApply // Update client-side field manager if transitioning from client-side to server-side apply
	results, err := u.cfg.KubeClient.Update(
		current,
		target,
		kube.ClientUpdateOptionForceReplace(u.ForceReplace),
		kube.ClientUpdateOptionServerSideApply(serverSideApply, u.ForceConflicts),
		kube.ClientUpdateOptionUpgradeClientSideFieldManager(upgradeClientSideFieldManager))
	if err != nil {
		u.cfg.recordRelease(originalRelease)
		u.reportToPerformUpgrade(c, upgradedRelease, results.Created, err)
		return
	}

View on GitHub (pinned to 2a29f1770b)

Solutions

  1. Find the hook resource (kubectl get jobs,pods -n <ns>) and read its logs; use annotation helm.sh/hook-delete-policy: before-hook-creation so failed hook pods survive for debugging.
  2. Fix the hook script, image, or the RBAC of the service account it runs with.
  3. Raise --timeout if the hook is merely slower than the wait window.
  4. If the hook is not needed for this change, run helm upgrade --no-hooks.

Example fix

# before: pre-upgrade migration hook fails and blocks every upgrade
metadata:
  annotations:
    helm.sh/hook: pre-upgrade

# after: keep failed hook pods around, then inspect and fix
metadata:
  annotations:
    helm.sh/hook: pre-upgrade
    helm.sh/hook-delete-policy: before-hook-creation
# kubectl logs job/<hook-name> -n <ns>
Defensive patterns

Strategy: try-catch

Type guard

func isPreUpgradeHookError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "pre-upgrade hooks failed")
}

Try / catch

if _, err := up.RunWithContext(ctx, "myrel", chart, vals); err != nil {
    if isPreUpgradeHookError(err) {
        // nothing was applied yet: inspect hook job/pod logs, fix hook or raise Timeout, then retry
    }
}

Prevention

When it happens

Trigger: A pre-upgrade hook job fails (bad script, missing ConfigMap), the hook image cannot be pulled, RBAC denies the hook's service account, the hook YAML is invalid, or the hook does not finish within --timeout.

Common situations: Database migration jobs that fail on bad SQL or lost connections; hook pods deleted by hook-delete-policy before logs could be read; --timeout too small for slow migrations; CI service account lacking permissions.

Related errors


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