What is CrashLoopBackOff?
CrashLoopBackOff is not an error in itself—it is a state. The container keeps starting, crashing, and restarting, so kubelet stretches the restart interval (back-off) to stop a restart storm. In plain terms: the container keeps dying, so kubelet is pausing briefly before trying again.
- Restart interval doubles: 10s → 20s → 40s … up to a maximum of 5 minutes
- The cause lives inside the container, so the real job is finding why it died
- Occurs when
restartPolicyisAlways(the default) orOnFailure
CrashLoopBackOff is a bundle of symptoms, not the root cause. Tweaking the manifest without looking at the exit code and logs is usually wasted effort. Always narrow it down in this order: exit code → logs → events.
Step 1: Get the overall picture
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# myapp-xxx 0/1 CrashLoopBackOff 5 3m
kubectl describe pod myapp-xxxIn the describe output, look at these two places first.
Last State: Terminated
Reason: Error
Exit Code: 1 ←
Events:
Warning BackOff ... Back-off restarting failed containerStep 2: Interpret the exit code
The exit code quickly narrows the cause.
| Exit Code | Meaning | Common causes |
|---|---|---|
| 0 | Clean exit | Main process finished its work and exited (not a daemon) |
| 1 | Generic application error | Code exception, missing config, dependency not reachable |
| 2 | Shell usage / command error | Typo in command/args |
| 126 | Cannot execute | No permission, not a binary |
| 127 | Command not found | Wrong command path, package not installed |
| 137 | SIGKILL (128+9) | OOMKilled or forced kill |
| 139 | SIGSEGV (128+11) | Segmentation fault (native crash) |
| 143 | SIGTERM (128+15) | Termination signal received normally |
Step 3: Check the logs — the most important clue
You need the logs of the previously crashed container, not the current one.
kubectl logs myapp-xxx # (or )
kubectl logs myapp-xxx --previous # when ←
kubectl logs myapp-xxx -c sidecar # whenIf restarts are fast, the container is gone before you can grab logs. Use --previous to see the last instance's logs—that's where the real cause shows up.
Fixes by cause
A. Application failed to start (Exit 1)
Usually missing config/env vars, or a failed DB connection.
kubectl logs myapp-xxx --previous
# : "ECONNREFUSED postgres:5432" → DB Service- Confirm env vars / ConfigMap / Secret are actually injected
- If it's a dependency startup-order problem, wait with
initContainers
initContainers:
- name: wait-db
image: busybox:1.36
command: ['sh','-c','until nc -z postgres 5432; do echo waiting; sleep 2; done']B. OOMKilled (Exit 137)
The kernel killed the container because it exceeded its memory limit.
kubectl describe pod myapp-xxx | grep -A3 'Last State'
# Reason: OOMKilledFix: raise the limit, or inspect the app's memory usage.
resources:
requests: { memory: 256Mi }
limits: { memory: 512Mi } # +JVM, Node, and similar runtimes ignore the container limit and size the heap from host memory, which leads to OOM. Cap them to the container limit with -XX:MaxRAMPercentage or --max-old-space-size.
C. Bad command/args (Exit 127/126)
kubectl logs myapp-xxx --previous
# "exec: \"node\": executable file not found" →When you override the image ENTRYPOINT, double-check the path and spelling, and drop into a shell for debugging.
kubectl run debug --rm -it --image=myapp:1.0 --command -- /bin/shD. Liveness probe failing
The app is fine, but livenessProbe is too aggressive, so kubelet keeps killing it. Exit code is 137/143 and the logs show no error.
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
initialDelaySeconds: 30 # boot
periodSeconds: 10
failureThreshold: 3
# boot startupProbe
startupProbe:
httpGet: { path: /healthz, port: 8080 }
failureThreshold: 30
periodSeconds: 5| Clue | Most likely cause |
|---|---|
| App error in logs + Exit 1 | Config / dependency issue (A) |
| Reason: OOMKilled, Exit 137 | Out of memory (B) |
| "not found" + Exit 127 | command / image issue (C) |
| Clean logs + periodic 137/143 | Misconfigured probe (D) |
E. Missing config resources (CreateContainerConfigError)
Strictly speaking this is the step before CrashLoop, but you often hit it together.
kubectl describe pod myapp-xxx
# Warning Failed ... configmap "app-config" not foundConfirm the referenced ConfigMap / Secret / key exists in the same namespace.
Live debugging techniques
# when — (/)
kubectl get events --sort-by=.lastTimestamp
# when (command sleep )
kubectl run probe --rm -it --image=myapp:1.0 \
--command -- sleep 3600
kubectl exec -it probe -- sh
# Pod ( without)
kubectl debug -it myapp-xxx --image=busybox:1.36 --target=myappTo inspect a live Deployment, temporarily kubectl edit the command to sleep. That stops the crash loop so you can investigate inside. Don't forget to revert afterward.
Recap
| Step | Command | What you get |
|---|---|---|
| Status | kubectl get/describe pod | STATUS, exit code, events |
| Exit code | Last State in describe | Cause category |
| Logs | kubectl logs --previous | The actual crash reason |
| Events | kubectl get events | Scheduling / image / config problems |
| Diagnose | kubectl run/exec/debug | Direct look inside the container |
| Exit code | First fix to try |
|---|---|
| 1 | Check logs → config / dependencies |
| 137 | Raise memory limit (OOMKilled) |
| 127/126 | Check command / image |
| 137/143 + clean logs | Relax probes / add startupProbe |
CrashLoopBackOff only means "retrying." The cause is always inside the container. Narrow it down exit code → --previous logs → events and you can systematically fix almost every case.
AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us
Questions & answers
Ask a question about this guide. We'll review and reply.