Helm hook failure blocks upgrade and deletes release resources
Helm upgrade fails with hook PreUpgrade or PreInstall error
Focused incident mode — strips away everything but this runbook.
Symptoms
- Helm upgrade fails with hook PreUpgrade or PreInstall error
- Release resources are deleted after a hook failure
- Helm status shows 'failed' with hook job errors and missing deployments
Helm hooks are the most dangerous part of a chart — a failing pre-install hook can delete a running production deployment. Test hooks in a staging environment with real data before shipping to production.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Release hook status and history
helm history <RELEASE> -n <NAMESPACE> --output json | jq '.[].hooks'Hook job pod logs
kubectl logs job/<HOOK_JOB_NAME> -n <NAMESPACE>
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- Hook job shows COMPLETIONS 0/1 and FAILED status
- Helm status shows 'failed' after the hook timeout
- Release resources were created but then cleaned up by Helm on hook failure
Confirm before fixing
kubectl get jobs -n <NAMESPACE> -l app.kubernetes.io/instance=<RELEASE> -o wideList all hook jobs and their completion status
Fix
helm delete <RELEASE> -n <NAMESPACE> --no-hooksRemove the failed release without running hook deletions
Expected: release "<RELEASE>" deleted
kubectl delete job <HOOK_JOB_NAME> -n <NAMESPACE> --ignore-not-foundClean up the stuck hook job before reinstalling
Expected: job.batch/<HOOK_JOB_NAME> deleted
helm install <RELEASE> <CHART> -n <NAMESPACE> -f values.yamlReinstall from scratch after fixing the hook cause
Expected: Release "<RELEASE>" has been installed
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
helm history <RELEASE> -n <NAMESPACE>Identify the failed revision and hook status
kubectl get deploy,svc -n <NAMESPACE> -l app.kubernetes.io/instance=<RELEASE>Check if the release resources still exist
kubectl logs job/<HOOK_JOB_NAME> -n <NAMESPACE>Read the hook failure reason
helm delete <RELEASE> -n <NAMESPACE> --no-hooksTear down the stuck release without running hook deletions
Expected: release "<RELEASE>" deleted
kubectl delete job <HOOK_JOB_NAME> -n <NAMESPACE> --ignore-not-foundClean up the failed hook job
helm install <RELEASE> <CHART> -n <NAMESPACE> -f values.yamlReinstall the release after fixing the hook cause
Expected: Release "<RELEASE>" has been installed
Prevention
- Add retryBackoff and backoffLimit to all hook Jobs to survive transient failures.
- Use helm.sh/hook-delete-policy: hook-succeeded to avoid premature resource cleanup.
- Make hooks idempotent — they should be safe to re-run without side effects.
- Run helm test after install to validate hooks in a separate post-install step.
Related runbooks
Same stack, same failure family — worth a skim.
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.