Kubernetes "PostStartHookError" - Fix Lifecycle postStart Failures in CI
A container’s lifecycle.postStart hook runs immediately after the container starts. If the hook command exits non-zero (or the HTTP probe fails), the kubelet considers startup failed, kills the container, and restarts it - looking like a crash loop driven by the hook.
What this error means
kubectl describe pod shows FailedPostStartHook / PostStartHookError events and the container restarts. The app binary itself may be fine - it is the postStart command that fails.
Warning FailedPostStartHook 8s kubelet Exec lifecycle hook ([sh -c
/setup.sh]) for Container "api" failed - error: command '/setup.sh' exited with
126: , message: "exec: \"/setup.sh\": permission denied"Common causes
postStart command fails or is missing
The exec hook points at a script that is absent, not executable, or returns non-zero. The kubelet treats a failed postStart as a startup failure and restarts the container.
Hook races the app
A postStart that depends on the app already listening can fail because postStart runs concurrently with the entrypoint, with no ordering guarantee.
How to fix it
Read the hook’s exit code and message
kubectl describe pod <pod> | grep -A3 -i poststartFix or remove the hook
- Exit 126/"permission denied" → make the script executable in the image (
chmod +x). - Exit 127/"not found" → correct the path or install the binary the hook calls.
- If the work belongs in startup, move it into the entrypoint or an initContainer instead of postStart.
How to prevent it
- Keep postStart hooks simple, executable, and independent of the app being ready.
- Prefer an initContainer for setup that must complete before the app runs.
- Test lifecycle hooks in staging before relying on them in production rollouts.