Kubernetes CrashLoopBackOff: Meaning, Diagnosis, and the 8 Fixes (2026)

CrashLoopBackOff explained — what it actually means, the kubectl diagnosis sequence, and the 8 root causes with fixes: config, probes, OOM, init containers, and more.

Best practices
Kubernetes CrashLoopBackOff: Meaning, Diagnosis, and the 8 Fixes (2026)

Short answer: CrashLoopBackOff means your container starts, crashes, and Kubernetes restarts it with growing delays (10s, 20s, 40s… up to 5 minutes) — it is not an error cause but a restart pattern. The actual cause is in the dead container's logs: kubectl logs <pod> --previous. The eight real causes: bad config/secrets, application exceptions, failing liveness probes, OOMKills, missing files or entrypoints, failed init containers, port/permission conflicts, and dependency unavailability at startup. Diagnosis sequence and all eight fixes below.

What CrashLoopBackOff actually means

Kubernetes always restarts failed containers (that's the feature). When a container exits non-zero, the kubelet restarts it; each successive crash doubles the backoff delay to a 5-minute cap. CrashLoopBackOff is simply the status Kubernetes shows while waiting out that backoff. Two implications: the pod may appear Running for seconds between crashes (check kubectl get pods repeatedly), and the "Back-off" delay is a symptom of repeated failure — the number you want is the exit code and the reason, not the status.

The diagnosis sequence (always in this order)

# 1. Status and restart count
kubectl get pod <pod> -n <ns>

# 2. The autopsy: Last State, Reason, Exit Code, Events
kubectl describe pod <pod> -n <ns>
#    Last State: Terminated  Reason: Error  Exit Code: 1
#    Events: Back-off restarting failed container

# 3. The dying container's own logs — 90% of answers live here
kubectl logs <pod> -n <ns> --previous --tail=100

# 4. If init containers are involved
kubectl logs <pod> -n <ns> -c <init-container-name> --previous

Related guideKubernetes Monitoring: The Complete 2026 Guide

The 8 root causes and their fixes

# Cause Signature in describe/logs Fix
2 Application exception at startup Exit 1; stack trace in --previous logs Fix the code path; test the same image locally with the same env
3 Liveness probe killing a slow starter Liveness probe failed events; app logs show normal startup Add startupProbe or raise initialDelaySeconds; probe a cheap endpoint
4 OOMKilled during boot Reason: OOMKilled, exit 137 JVM/heap vs container limit mismatch — raise limit or cap heap (-Xmx below limit)
6 Init container failing Pod stuck Init:CrashLoopBackOff; init logs show the error Debug with logs -c <init> — usually a dependency wait or migration error
7 Port or permission conflict bind: address already in use, permission denied Fix container port, run-as user (securityContext), or file ownership
8 Dependency unavailable at startup Logs: connection refused to DB/queue/DNS Add retry/backoff in app, or an init container that waits for the dependency

The four most common, with exact commands

Missing config (cause 1):

Related guideKubernetes Integration

kubectl describe pod <pod> | grep -A5 Events   # "couldn't find key DATABASE_URL in Secret/app-secrets"
kubectl get secret app-secrets -o yaml          # confirm the key name — typos are the classic

Startup crash (cause 2):

kubectl logs <pod> --previous --tail=200        # read the actual stack trace
# Reproduce locally with identical env:
docker run --rm -e DATABASE_URL=... <image>:<tag>

Probe-kills-starter (cause 3) — common with JVM apps that need 40s to boot but a liveness probe firing at 10s:

startupProbe:                  # let the app finish booting before liveness applies
  httpGet: { path: /healthz, port: 8080 }
  failureThreshold: 30
  periodSeconds: 10            # 30 × 10s = 5 min of startup grace

Boot OOM (cause 4):

kubectl describe pod <pod> | grep -B2 OOMKilled
# If the app is Java: container limit 512Mi but JVM default heap ratios blow past it
# Fix: -XX:MaxRAMPercentage=75 or an explicit -Xmx below the limit

Preventing the next one

  • Alert on it directly: kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff"} == 1 — don't wait for users to report a deployment that never came up.
  • Rollouts that catch it: use progressive delivery (Argo Rollouts/Flagger) or at minimum maxUnavailable: 0 so a crashing new version never takes the old one down with it.
  • StartupProbe on every slow-starting service — the 60-second fix that eliminates the whole probe-misfire class.
  • Centralized logs, because kubectl logs --previous only works while the pod object still exists; in a busy cluster the evidence rotates away.

FAQ

Q: What does CrashLoopBackOff mean in Kubernetes?
It means a container in the pod starts and crashes repeatedly, and Kubernetes is waiting out an exponentially growing delay (up to 5 minutes) before the next restart. It describes the restart pattern, not the cause — the cause is in the terminated container's logs (kubectl logs <pod> --previous) and the exit code in kubectl describe pod.

Q: How do I fix CrashLoopBackOff?
Diagnose first: kubectl describe pod (exit code + reason) and kubectl logs --previous (the error). Then match the cause: missing config/secret → create it; app exception → fix code; liveness probe misfire → add a startupProbe; OOMKilled → raise memory limit or cap app heap; bad entrypoint → fix command/args; failing init container → debug it with logs -c <init>.

Q: Why does my pod show Running then CrashLoopBackOff alternately?
Because the container genuinely starts, survives seconds-to-minutes, then crashes — Kubernetes restarts it after backoff, it starts again, crashes again. The Running windows are the crash cycles, not recovery. Watch RESTARTS climb in kubectl get pods -w and read --previous logs to see what's killing it each cycle.

Q: Can a liveness probe cause CrashLoopBackOff?
Yes — one of the most common causes. If the app starts slower than the probe's initialDelaySeconds + failureThreshold window, the kubelet kills a healthy-but-booting container, which restarts and gets killed again. The fix is a startupProbe (which suspends liveness checks until startup succeeds), not a longer liveness delay.

Q: How do I check CrashLoopBackOff logs after the pod is deleted?
You can't — --previous requires the pod object. This is why production clusters ship container logs to centralized storage (Loki, Elasticsearch, Guance, CloudWatch Logs). With centralized logs, the crashing container's output remains queryable by pod name long after the pod is gone.


Sources: Kubernetes documentation (container restart policy, probes, pod lifecycle). Verified 2026-08-07. Canonical page consolidating the "-fix" variant.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting