CrashLoopBackOff in Kubernetes: Causes, Exit Codes, and How to Fix It
Updated Sep 2026 · Tested on Kubernetes 1.30+
A pod will not come up. You look closer and it is stuck in CrashLoopBackOff: the container starts, crashes, and restarts over and over. There are many possible causes, but a small set of diagnostic steps will isolate almost all of them. This guide explains what the state means, how to read the exit codes, and the exact kubectl commands to find and fix the root cause.
What is CrashLoopBackOff?
CrashLoopBackOff is a pod state indicating that a container inside the pod has entered a restart loop. It repeatedly starts, crashes, and is restarted by the kubelet with a growing delay between attempts.
The important thing to understand: CrashLoopBackOff is a symptom, not the root cause. It tells you a container keeps exiting. It does not tell you why. The why is in the logs and the exit code.
What “BackOff” means
When a container crashes, the kubelet on that node automatically restarts it. If it crashes again immediately, Kubernetes “backs off” by waiting longer before the next attempt, so a broken container does not exhaust node CPU, memory, and API server load with constant restarts.
The delay is exponential — each failure roughly doubles the wait:
| Attempt | Delay before restart |
|---|---|
| 1st | 10s |
| 2nd | 20s |
| 3rd | 40s |
| 4th | 80s |
| 5th | 160s |
| 6th and beyond | 300s (5 min cap) |
The delay caps at 5 minutes. After the container runs successfully for about 10 minutes, the backoff counter resets and the delay curve starts over from 10 seconds.
One consequence worth knowing: because the delay caps at 5 minutes, a slow crash loop can look like an intermittent outage rather than a hard failure. If a service flaps every few minutes, suspect a crash loop and check the logs.
How to diagnose CrashLoopBackOff
The whole diagnosis is a short loop: get the pod, read the previous logs, read the exit code and events.
1. Find the pod
kubectl get pods
Look for the pod with STATUS: CrashLoopBackOff and a climbing RESTARTS count.
2. Read the previous container’s logs
This is the most important step, and the flag matters. Read the previous container’s logs, because the crashed container has already been replaced by the current one:
kubectl logs <pod-name> --previous
The crash message is usually right here: a stack trace, a “connection refused,” a “missing environment variable,” or a failed database migration.
3. Check the exit code and events
kubectl describe pod <pod-name>
Look at the Last State, its Exit Code, and the Events at the bottom. The exit code narrows the cause quickly.
Reading the exit codes
| Exit code | Meaning | Usual cause |
|---|---|---|
1 | Application error | Missing env var, unreachable dependency at startup, failed migration, bad config |
137 | SIGKILL (128 + 9) | OOMKilled — memory limit too low, or a leak. Also a failed liveness probe kill |
139 | Segfault (128 + 11) | The process accessed memory it should not — often a native/library bug |
143 | SIGTERM (128 + 15) | Graceful termination; the container was asked to stop |
A non-zero application exit (like 1) points at configuration: a missing environment variable, an unreachable dependency at startup, or a failing migration.
Exit code 137 with Reason: OOMKilled means the memory limit is too low or the app has a leak. Check and raise the limit, or fix the leak:
kubectl describe pod <pod-name> | grep -A5 "Last State"
# Look for: Reason: OOMKilled Exit Code: 137
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[*].resources}'
When the liveness probe is the culprit
If the container starts fine and is then killed on a regular timing that matches your probe interval, the liveness probe is likely the problem, not the app:
- The liveness probe is too aggressive (fails before the app can respond).
- The
initialDelaySecondsis shorter than real startup time, so the probe kills the app while it is still warming up.
For a slow-starting app, add a startupProbe so the liveness probe does not kill it during warm-up, or relax the liveness initialDelaySeconds and failureThreshold.
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 2 # allows up to 60s to start before liveness begins
The fix, in one sentence
Do not try to fix the backoff — it is doing its job. Read kubectl logs --previous and the exit code from kubectl describe pod, identify the real reason the container exits, and fix that: the config, the memory limit, the dependency, or the probe.
Where to go next
Exit codes come up all over Linux, not just Kubernetes. For the full list and how the 128+signal convention works, see bash exit codes and Linux error codes. For the kubectl commands to inspect pods and events day to day, see the Kubernetes commands you must know reference, and to understand where a crashing pod sits in the request path, how traffic flows in Kubernetes.