criticalAdvancedSymptom-first#helm#hooks#pre-install#job#release-stuck

Helm hook failure blocks upgrade and deletes release resources

Helm upgrade fails with hook PreUpgrade or PreInstall error

Likely source:deploymentavailabilitydata-loss

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 wide
READ

List all hook jobs and their completion status

Fix

helm delete <RELEASE> -n <NAMESPACE> --no-hooks
DESTRUCTIVE

Remove the failed release without running hook deletions

Expected: release "<RELEASE>" deleted

kubectl delete job <HOOK_JOB_NAME> -n <NAMESPACE> --ignore-not-found
CHANGE

Clean up the stuck hook job before reinstalling

Expected: job.batch/<HOOK_JOB_NAME> deleted

helm install <RELEASE> <CHART> -n <NAMESPACE> -f values.yaml
CHANGE

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

1
helm history <RELEASE> -n <NAMESPACE>
READ

Identify the failed revision and hook status

2
kubectl get deploy,svc -n <NAMESPACE> -l app.kubernetes.io/instance=<RELEASE>
READ

Check if the release resources still exist

3
kubectl logs job/<HOOK_JOB_NAME> -n <NAMESPACE>
READ

Read the hook failure reason

4
helm delete <RELEASE> -n <NAMESPACE> --no-hooks
DESTRUCTIVE

Tear down the stuck release without running hook deletions

Expected: release "<RELEASE>" deleted

5
kubectl delete job <HOOK_JOB_NAME> -n <NAMESPACE> --ignore-not-found
CHANGE

Clean up the failed hook job

6
helm install <RELEASE> <CHART> -n <NAMESPACE> -f values.yaml
CHANGE

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

Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.