{"record":{"id":"76d775855abacf73","repo":"helm/helm","slug":"pre-upgrade-hooks-failed-w","errorCode":null,"errorMessage":"pre-upgrade hooks failed: %w","messagePattern":"pre-upgrade hooks failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/action/upgrade.go","lineNumber":461,"sourceCode":"\t\terr := ctx.Err()\n\n\t\t// when RollbackOnFailure is set, the ongoing release finish first and doesn't give time for the rollback happens.\n\t\tu.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, err)\n\tcase <-done:\n\t\treturn\n\t}\n}\n\nfunc isReleaseApplyMethodClientSideApply(applyMethod string) bool {\n\treturn applyMethod == \"\" || applyMethod == string(release.ApplyMethodClientSideApply)\n}\n\nfunc (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *release.Release, current kube.ResourceList, target kube.ResourceList, originalRelease *release.Release, serverSideApply bool) {\n\t// pre-upgrade hooks\n\n\tif !u.DisableHooks {\n\t\tif err := u.cfg.execHook(upgradedRelease, release.HookPreUpgrade, u.WaitStrategy, u.WaitOptions, u.Timeout, serverSideApply); err != nil {\n\t\t\tu.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, fmt.Errorf(\"pre-upgrade hooks failed: %w\", err))\n\t\t\treturn\n\t\t}\n\t} else {\n\t\tu.cfg.Logger().Debug(\"upgrade hooks disabled\", \"name\", upgradedRelease.Name)\n\t}\n\n\tupgradeClientSideFieldManager := isReleaseApplyMethodClientSideApply(originalRelease.ApplyMethod) && serverSideApply // Update client-side field manager if transitioning from client-side to server-side apply\n\tresults, err := u.cfg.KubeClient.Update(\n\t\tcurrent,\n\t\ttarget,\n\t\tkube.ClientUpdateOptionForceReplace(u.ForceReplace),\n\t\tkube.ClientUpdateOptionServerSideApply(serverSideApply, u.ForceConflicts),\n\t\tkube.ClientUpdateOptionUpgradeClientSideFieldManager(upgradeClientSideFieldManager))\n\tif err != nil {\n\t\tu.cfg.recordRelease(originalRelease)\n\t\tu.reportToPerformUpgrade(c, upgradedRelease, results.Created, err)\n\t\treturn\n\t}","sourceCodeStart":443,"sourceCodeEnd":479,"githubUrl":"https://github.com/helm/helm/blob/2a29f1770b62844b27197d2507377361d45ad7c0/pkg/action/upgrade.go#L443-L479","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Fix the hook script, image, or the RBAC of the service account it runs with.","Raise --timeout if the hook is merely slower than the wait window.","If the hook is not needed for this change, run helm upgrade --no-hooks."],"exampleFix":"# before: pre-upgrade migration hook fails and blocks every upgrade\nmetadata:\n  annotations:\n    helm.sh/hook: pre-upgrade\n\n# after: keep failed hook pods around, then inspect and fix\nmetadata:\n  annotations:\n    helm.sh/hook: pre-upgrade\n    helm.sh/hook-delete-policy: before-hook-creation\n# kubectl logs job/<hook-name> -n <ns>","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isPreUpgradeHookError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"pre-upgrade hooks failed\")\n}","tryCatchPattern":"if _, err := up.RunWithContext(ctx, \"myrel\", chart, vals); err != nil {\n    if isPreUpgradeHookError(err) {\n        // nothing was applied yet: inspect hook job/pod logs, fix hook or raise Timeout, then retry\n    }\n}","preventionTips":["Annotate hooks with helm.sh/hook-delete-policy: before-hook-creation so failed pods stay inspectable.","Set --timeout generously for migration-style hooks.","Test hook jobs against staging clusters before production upgrades."],"tags":["helm","hooks","upgrade","jobs"],"backgroundTag":null,"analyzedSha":"2a29f1770b62844b27197d2507377361d45ad7c0","analyzedAt":"2026-08-15T22:02:47.490Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}