Introduction

Helm post-delete hooks run after the main resources are deleted during helm uninstall. These hooks typically perform cleanup tasks like removing external resources, sending notifications, or archiving data. When a post-delete hook resource gets stuck -- such as a Job that cannot complete or a Pod stuck in Terminating -- the uninstall process hangs, leaving orphaned resources in the namespace.

Symptoms

  • helm uninstall hangs indefinitely waiting for the post-delete hook to complete
  • Namespace cannot be deleted because hook resources are still present
  • kubectl get all shows hook jobs or pods stuck after uninstall
  • Hook Job has Active status but no pods are running
  • Error message: timed out waiting for the condition during uninstall

Common Causes

  • Post-delete hook Job's container image not available, causing image pull errors
  • Hook depends on a resource that was already deleted (e.g., ConfigMap or Secret)
  • Hook Job has no activeDeadlineSeconds and runs indefinitely
  • Namespace deletion triggered while hook is still running
  • Hook pod stuck in Terminating due to finalizer on a custom resource

Step-by-Step Fix

  1. 1.Identify the stuck hook resource: Check what is blocking the uninstall.
  2. 2.```bash
  3. 3.kubectl get jobs -n my-namespace
  4. 4.kubectl get pods -n my-namespace | grep hook
  5. 5.`
  6. 6.Delete the stuck hook resource manually: Force cleanup of the hook.
  7. 7.```bash
  8. 8.# Delete the stuck job
  9. 9.kubectl delete job my-release-cleanup-hook -n my-namespace --force --grace-period=0
  10. 10.# Remove any stuck pods
  11. 11.kubectl delete pod my-release-cleanup-hook-xxxxx -n my-namespace --force --grace-period=0
  12. 12.`
  13. 13.Remove finalizers if the resource is stuck in Terminating: Force deletion.
  14. 14.```bash
  15. 15.kubectl patch pod my-release-hook-xxxxx -n my-namespace \
  16. 16.-p '{"metadata":{"finalizers":[]}}' --type=merge
  17. 17.`
  18. 18.Clean up remaining Helm release data: Remove the release secret.
  19. 19.```bash
  20. 20.kubectl get secrets -n my-namespace -l owner=helm,name=my-release
  21. 21.kubectl delete secret sh.helm.release.v1.my-release.v1 -n my-namespace
  22. 22.`
  23. 23.Fix the hook for future uninstalls: Add timeout and error handling.
  24. 24.```yaml
  25. 25.apiVersion: batch/v1
  26. 26.kind: Job
  27. 27.metadata:
  28. 28.name: "{{ .Release.Name }}-cleanup"
  29. 29.annotations:
  30. 30."helm.sh/hook": post-delete
  31. 31."helm.sh/hook-delete-policy": before-hook-creation
  32. 32.spec:
  33. 33.activeDeadlineSeconds: 120
  34. 34.backoffLimit: 1
  35. 35.template:
  36. 36.spec:
  37. 37.containers:
  38. 38.- name: cleanup
  39. 39.image: busybox
  40. 40.command: ["sh", "-c", "echo cleanup && exit 0"]
  41. 41.restartPolicy: Never
  42. 42.`

Prevention

  • Set activeDeadlineSeconds on all hook jobs to prevent indefinite execution
  • Use helm.sh/hook-delete-policy: before-hook-creation to clean up hook resources before running
  • Design post-delete hooks to be idempotent and tolerant of missing dependencies
  • Test helm uninstall in staging environments to identify hook issues before production
  • Monitor hook job completion in CI/CD pipelines after uninstall
  • Keep post-delete hooks simple -- use them only for critical cleanup, not complex operations