Skip to main content

Kubernetes · troubleshooting

CrashLoopBackOff

A container starts, exits, and Kubernetes restarts it — repeatedly. The loop itself is not the fault; it is the symptom of whatever makes the container exit.

Run this first

step 1 of 3
kubectl describe pods <pod>

Look for Last State reason and exit code; probe failure events; missing-object events

The Kubernetes documentation names this as the primary debugging command. Events at the bottom usually name the failure outright, and Last State gives you the exit code.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

In kubectl describe pod, what does Last State say the container terminated with?

Look for the Last State block. The reason and exit code narrow this faster than anything else.

Cause space

5 of 5 still possible

  • The application exits on startupCommon
  • The container is being OOMKilledCommon
  • The liveness probe is failingCommon
  • A referenced ConfigMap, Secret or volume does not existOccasional
  • The image entrypoint or command is wrongOccasional

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Check it with a tool

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    kubectl describe pods <pod>

    The Kubernetes documentation names this as the primary debugging command. Events at the bottom usually name the failure outright, and Last State gives you the exit code.

    Look for Last State reason and exit code; probe failure events; missing-object events

  2. Step 2

    kubectl logs <pod> --previous

    The current container has not produced output yet — it is waiting out the backoff. --previous shows the run that actually failed.

    Look for The application's own error on the way down

  3. Step 3

    kubectl get events --sort-by=.lastTimestamp -n <namespace>

    Widens the view when the pod's own events are not enough — scheduling, image and node problems appear here.

    Look for Anything about this pod in the minutes before the first restart

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

The application exits on startup

Common

The most common case, and the least glamorous: the process itself fails. A missing environment variable, an unreachable database at boot, a config file that is not where the code expects, an unhandled exception during initialisation. The container is doing exactly what it was told; the program is wrong.

Confirm

kubectl logs <pod> --previous

A stack trace or fatal error from the run that just died. --previous is the important part: without it you get the container that is currently waiting to start, which has produced no output yet.

Fix

  • Read the actual error. In most cases the container is telling you precisely what is missing.
  • Check that every environment variable and mounted file the process reads at startup exists in this namespace.
  • If it depends on another service being reachable at boot, either make the dependency optional with retries, or use an init container so the failure is reported honestly instead of as a crash loop.

The container is being OOMKilled

Common

The container exceeded its memory limit and the kernel terminated it. This presents as a crash loop because the restart succeeds, memory climbs again, and it is killed again. Exit code 137 is the signature.

Confirm

kubectl describe pod <pod> | grep -A3 'Last State'

Reason: OOMKilled, and Exit Code: 137

Fix

  • Raise the memory limit if the workload genuinely needs more than it was given.
  • If usage grows without bound, this is a leak and raising the limit only lengthens the interval between kills.

The liveness probe is failing

Common

A liveness probe that fails causes the kubelet to kill and restart the container — by design. If the probe is stricter than the application's real startup time, Kubernetes kills a healthy process before it ever finishes booting, forever. This one is cruel because nothing is actually broken.

Confirm

kubectl describe pod <pod>

Events containing "Liveness probe failed". Compare initialDelaySeconds and the probe path against how long the app really takes to serve traffic.

Fix

  • Use a startup probe for slow-booting applications so the liveness probe only begins once the app is up.
  • Point the probe at an endpoint that means "this process is alive", not one that checks downstream dependencies — otherwise a database blip restarts your app.

A referenced ConfigMap, Secret or volume does not exist

Occasional

The pod references something absent from the namespace. Depending on how it is referenced this can surface as a crash loop rather than a clear mount error, particularly when the application reads the file itself and exits on failure.

Confirm

kubectl describe pod <pod>

Events mentioning a ConfigMap, Secret or volume that cannot be found

Fix

  • Create the missing object, or correct the name in the pod spec.
  • Confirm you are looking in the right namespace — this is very often a namespace mismatch rather than a missing object.

The image entrypoint or command is wrong

Occasional

A command that does not exist in the image, or one that runs to completion and exits 0. Kubernetes restarts a container that exits successfully too, if the restart policy says so — a one-shot script in a Deployment will crash-loop while behaving perfectly.

Confirm

kubectl logs <pod> --previous

"executable file not found", "no such file or directory", or no output at all with exit code 0

Fix

  • Verify the command exists inside the image: docker run --rm --entrypoint sh <image> -c 'which <cmd>'.
  • If the workload is genuinely meant to run once and exit, it is a Job, not a Deployment.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

What is actually happening

Kubernetes restarted your container, it exited again, and the kubelet is now waiting before trying once more. Each failure increases that wait exponentially, so the pod spends most of its time deliberately doing nothing. Widely-cited figures put the progression at roughly 10s, 20s, 40s and so on, capped at five minutes — that cap is why a broken pod appears to stop changing.

It is worth being precise about one thing, because it changes where you look: CrashLoopBackOff is a value kubectl shows in the STATUS column, not a pod phase. The Kubernetes documentation explicitly warns against confusing the two — phase is part of the API, STATUS is a display field assembled for human intuition. There is no CrashLoopBackOff condition to query; you are reading a summary of container state.

So the useful question is never "how do I fix CrashLoopBackOff". It is "why did the container exit", and the answer is almost always in the previous container's logs or in the pod's events.

How to tell this is your problem
WhereWhat you see
kubectl get podsSTATUS shows CrashLoopBackOff and RESTARTS climbs
kubectl describe podEvents include "Back-off restarting failed container"
Last StateTerminated with a non-zero exit code, or with reason OOMKilled

How to know it is actually fixed

  • RESTARTS stops incrementing. Check twice, a few minutes apart — the five-minute backoff cap means a broken pod can look calm.
  • kubectl get pod shows Running with all containers ready, not just Running.
  • kubectl logs <pod> (without --previous) shows the application's normal startup output.

Stopping it happening again

  • Use a startup probe wherever boot time is variable, so liveness never races initialisation.
  • Set memory requests and limits from observed usage, not from a round number.
  • Make startup dependencies retry rather than exit, so a transient outage does not become a crash loop.
  • Keep liveness probes checking only the process itself; check dependencies with readiness.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Related

CrashLoopBackOff — causes, diagnosis and fix | DevOps Insights