How to Fix CrashLoopBackOff in Kubernetes
CrashLoopBackOff means your container keeps dying on startup and Kubernetes keeps restarting it slower each time. Here's the diagnosis flow we actually use.
Key takeaways
- CrashLoopBackOff means your container keeps dying on startup and Kubernetes keeps restarting it slower each time.
- Here's the diagnosis flow we actually use.
On this page
How to Fix CrashLoopBackOff in Kubernetes
A pod goes CrashLoopBackOff and half the team starts guessing. It's almost never a mystery once you read the right output, and the order you read it in matters more than any single command.
Here's what the status actually means. Your container starts, runs for a bit (sometimes milliseconds), and exits. Kubernetes restarts it. It exits again. After a few rounds the kubelet stops restarting immediately and starts waiting: 10s, 20s, 40s, doubling up to a 5-minute cap. That growing delay is the "backoff." The "crashloop" is the part where your process refuses to stay up. So CrashLoopBackOff is not an error in itself, it's Kubernetes telling you it's tired of restarting something that won't stay alive.
The container is crashing. Your job is to find out why it exited, not why Kubernetes backed off.
The diagnosis flow#
Start here, every time. First look at the pod:
kubectl get pods
NAME READY STATUS RESTARTS AGE
api-7d9f8c6b4-2xqzk 0/1 CrashLoopBackOff 6 4m12s
Six restarts in four minutes. Now describe it:
kubectl describe pod api-7d9f8c6b4-2xqzk
Scroll to the container state and the events at the bottom. This is the single most useful block:
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 1
Started: Wed, 08 Jul 2026 10:22:14 +0000
Finished: Wed, 08 Jul 2026 10:22:14 +0000
Restart Count: 6
Started and Finished at the same second means the process died on boot. The exit code is your first real clue (more on codes below).
Now the opinionated part: read the previous container's logs before anything else.
kubectl logs api-7d9f8c6b4-2xqzk --previous
The --previous flag is the whole game. Without it, kubectl logs shows the current container, which may be freshly restarted and empty, or already dead again by the time you run it. --previous shows the instance that actually crashed. Nine times out of ten the stack trace or panic is sitting right there, and you can skip the guessing entirely.
If logs are empty, check events across the namespace:
kubectl get events --sort-by=.lastTimestamp
That surfaces the things logs won't: failed mounts, image pull problems, OOM kills, probe failures.
Common causes and how to fix them#
Application error or unhandled exception (exit 1). The most common case. Your app throws on startup: a nil pointer, an unhandled promise rejection, a bad migration. --previous logs show the trace. Fix the code or roll back the image. Exit code 1 is a generic application failure, so treat the logs as truth, not the code.
Bad or missing config / env var. The app starts, can't find DATABASE_URL or a required flag, and bails. Logs usually say something like panic: required env DATABASE_URL not set. Check what the pod actually received:
kubectl exec api-7d9f8c6b4-2xqzk -- env | grep DATABASE
If the pod won't stay up long enough to exec, inspect the ConfigMap and Secret refs in the deployment spec directly. A typo'd configMapKeyRef name silently gives you nothing.
Failed dependency (DB not reachable). The app boots, tries to connect to Postgres or Redis, times out, and exits instead of retrying. Logs show connection refused or a DNS failure. Two fixes: make the app retry with backoff instead of dying, and confirm the dependency is actually up and its Service resolves:
kubectl exec api-7d9f8c6b4-2xqzk -- nslookup postgres.default.svc.cluster.local
A hard crash on a transient dependency blip is a bug in your app, not in Kubernetes. Startup dependencies should be patient.
Failing liveness probe killing a healthy app. This one fools people. The app is fine but slow to warm up, the liveness probe hits /healthz before the app is ready, fails, and the kubelet kills the container. Restart, repeat, CrashLoopBackOff. You'll see it in describe:
Warning Unhealthy kubelet Liveness probe failed: HTTP probe failed with statuscode: 500
Normal Killing kubelet Container failed liveness probe, will be restarted
The fix is a startupProbe, or a longer initialDelaySeconds / failureThreshold on the liveness probe. Liveness should catch a wedged app, not punish a slow boot.
OOMKilled (exit 137). The container hit its memory limit and the kernel killed it. Describe shows Reason: OOMKilled and Exit Code: 137 (128 + signal 9). Either the limit is too low or the app is leaking. Raise resources.limits.memory if the workload legitimately needs it, or fix the leak. Don't just keep bumping the limit forever.
Missing file or permission denied. Often after switching to a non-root user or a read-only filesystem. Logs show permission denied or no such file or directory. Check your securityContext, volume mounts, and whether the image expects to write somewhere it no longer can.
Wrong command or entrypoint (exit 127 / 126). Exit 127 is "command not found," 126 is "found but not executable." Usually a bad command: / args: override in the manifest, or a typo in the binary path. The container never really runs your app at all.
Exit codes worth memorizing#
- 0 — clean exit. If it's crashlooping on 0, your process finishes and has nothing to keep it running.
- 1 — generic app error. Read the logs.
- 126 / 127 — entrypoint not executable / not found.
- 137 — SIGKILL, almost always OOMKilled or a probe kill.
- 139 — SIGSEGV, a segfault.
- 143 — SIGTERM, graceful shutdown that exited too fast.
The checklist#
Run these in order and you'll rarely get stuck:
kubectl get pods— confirm the status and restart count.kubectl describe pod <pod>— read Last State, Reason, and Exit Code.kubectl logs <pod> --previous— read the crash from the dead container first.kubectl get events --sort-by=.lastTimestamp— catch mounts, probes, OOM, image pulls.- Map the exit code (137 = memory, 127 = entrypoint, 1 = app error).
- Reproduce locally with the same image and env if the logs aren't enough.
- Check probes before assuming the app is broken.
If you want a broader reference for the surrounding failure modes, our Kubernetes troubleshooting guide covers the pod lifecycle states around this one.
The call we'd make#
Read --previous logs first, always. Everything else is confirmation. The exit code narrows it (137 sends you to memory and probes, 127 to your entrypoint, 1 to the application), but the crashed container's own log line is what tells you the truth. Resist the urge to bump memory limits or loosen probes before you've actually read why the thing died, because the fastest fix is the one aimed at the real cause.
Get the DevOps Troubleshooting Cheat Sheet
Subscribe and get our free one-page reference for the errors that eat an afternoon — CrashLoopBackOff, OOMKilled, Terraform state locks, and more — plus new guides as we publish them.
AWS Graviton Migration: What Broke and What We Saved
Moving our fleet from x86 to Graviton promised 20% savings. We got 31%, but only after fixing native dependencies, a broken base image, and one nasty perf regression.
GitHub Actions Best Practices in 2026: Workflows You Can Trust
A production-focused GitHub Actions guide: reusable workflows, least-privilege permissions, keyless OIDC to the cloud, SHA-pinned actions, environments with approvals, concurrency-safe deploys, and CodeQL/Dependabot gates — with copy-paste examples.
More from DevOps
Explore more articles in this category
The State of DevOps and AI Tooling in 2026: What the Data Actually Shows
A synthesis of this year's major industry surveys (Stack Overflow, GitHub Octoverse, CNCF, DORA, and more), with the actual numbers and what they mean for a working team.
Business Logic Vulnerabilities: The Flaws Scanners Can't Find
Business logic vulnerabilities exploit legitimate application workflows rather than broken code, so scanners routinely miss them entirely.
GraphQL Security Best Practices
GraphQL's single flexible endpoint creates attack surfaces REST checklists miss, from introspection exposure to query depth and batching abuse.
You might have missed
Evergreen posts worth revisiting.