CrashLoopBackOff vs ImagePullBackOff vs Error: a pod status taxonomy
A field map of every Kubernetes pod status - CrashLoopBackOff, ImagePullBackOff, Pending, Error - and the first command to run for each one.
kubectl get pods gives you one word per pod, and that word is doing a lot of work. Every
Kubernetes pod status is a compressed diagnosis: it tells you which subsystem gave up, which
means it tells you where to look first. Engineers who resolve incidents fast aren't faster at
typing - they've internalized the map from status to entry point, so they skip the ten minutes
of flailing.
This post is that map. For each status: what it actually means, the one command that opens the right door, and a link to the full field guide where one exists.
One clarification before we start: the STATUS column is not a single field. It's a summary
computed from the pod's phase, container states, and waiting reasons. CrashLoopBackOff isn't a
phase - it's a container waiting reason surfaced to save you a describe. That's why the
same underlying failure can show different statuses at different moments.
The taxonomy: every Kubernetes pod status, decoded
Pending
The pod object exists, but no containers have started. Either the scheduler can't place it, or the node accepted it and is stuck preparing (pulling images, attaching volumes).
kubectl describe pod <pod> | sed -n '/Events:/,$p'
If you see FailedScheduling, read the scheduler's arithmetic - it lists exactly how many
nodes failed and why (Insufficient cpu, node(s) had untolerated taint). The complete
decision tree is in Pod stuck in Pending: the complete diagnostic
tree. If events show FailedMount or
FailedAttachVolume, it's a storage problem, not a scheduling one.
ContainerCreating
Scheduled, but the kubelet is still assembling the sandbox. Normal for a few seconds. Stuck for
minutes means volumes, secrets, or the CNI plugin. Same command: describe, read events. A pod
stuck here with no events at all often means the kubelet itself is unwell - check
journalctl -u kubelet on the node.
ImagePullBackOff / ErrImagePull
The runtime can't fetch the image. ErrImagePull is the attempt failing;
ImagePullBackOff is Kubernetes waiting longer between retries. The event text contains the
actual registry error:
Failed to pull image "myapp:v1.2.4": rpc error: code = NotFound
NotFound is a typo'd tag; unauthorized is a credentials problem; toomanyrequests is a
rate limit. Ordered checklist, fastest first, in Fixing ImagePullBackOff: every cause, fastest
check first.
CreateContainerConfigError
The image is fine - the configuration the container needs doesn't exist. Almost always a ConfigMap or Secret referenced by name (or key) that isn't there:
Error: configmap "app-config" not found
Full decoding of every variant in CreateContainerConfigError: the ConfigMap/Secret mistakes behind it.
CrashLoopBackOff
The container starts, dies, and Kubernetes is backing off between restarts (10s doubling to a cap of 5 minutes). The status tells you nothing about why it dies - that's in the previous container's logs:
kubectl logs <pod> --previous
The eight real causes and their fastest paths are in Debugging CrashLoopBackOff: a field guide.
Error
A one-shot container (usually a Job) exited non-zero and won't be restarted, or a pod-level
failure occurred. Same first move as CrashLoopBackOff: read the logs, then read the exit code
in Last State.
OOMKilled
Technically a termination reason, not a status, but you'll see it in describe constantly:
the kernel killed the container for exceeding its memory limit. Exit code 137. Diagnosis and
the JVM gotchas live in OOMKilled and exit code 137: finding the real memory
hog.
Completed
Exit code 0. For a Job, this is success. For a Deployment, it's a bug - your container ran to
completion instead of serving, and Kubernetes will restart it, eventually producing
CrashLoopBackOff with exit code 0. Usually a wrong entrypoint or a foregrounding mistake
(nginx without daemon off;).
Terminating
Deletion requested, but the pod won't go. Either the app is ignoring SIGTERM (wait out
terminationGracePeriodSeconds), or a finalizer is blocking the delete. If it's been stuck
for hours, someone force-deleted the wrong thing or a controller is down.
Evicted / Unknown
Evicted: the node ran out of a resource and the kubelet sacrificed this pod - the message in
describe names the resource. Unknown: the node stopped reporting; the pod may be running
fine, but the control plane can't see it. Both are node problems wearing a pod costume.
The three questions that classify any pod failure
If you forget the table, you can reconstruct it. Every pod status answers three questions:
- Did it schedule? No →
Pending. Scheduler or resource problem. - Did the container start? No →
ImagePullBackOff,CreateContainerConfigError,ContainerCreating. Image, config, or node problem. - Did it stay up? No →
CrashLoopBackOff,Error,OOMKilled. Application or resource problem - and now the exit code is your best witness.137is SIGKILL (usually OOM),143is SIGTERM,1is the app's own decision,126/127are entrypoint mistakes. The full table is in Kubernetes exit codes explained.
The order matters. A CrashLoopBackOff investigation that starts with the scheduler is wasted
motion; a Pending investigation that starts with application logs will find no logs to read.
In a graded incident, that wasted motion is exactly what separates transcripts - this taxonomy
is the difference between a straight line and a random walk.
Statuses that lie (or at least mislead)
Runningdoesn't mean working. A pod can beRunningand failing its readiness probe, receiving no traffic.kubectl get podsshowsREADY 0/1- read both columns.CrashLoopBackOffwith exit code 0 means the app is exiting successfully - Kubernetes restarts it because a Deployment expects a long-running process.Init:prefixes (Init:0/2,Init:CrashLoopBackOff) mean the main container is innocent; debug the init container withkubectl logs <pod> -c <init-container>.- A healthy status right after apply proves nothing. Watch it:
kubectl get pods -wfor two backoff cycles before declaring victory.
FAQ
What's the difference between pod phase and pod status?
Phase is the coarse five-value field on the pod object (Pending, Running, Succeeded,
Failed, Unknown). The STATUS column in kubectl get pods is a friendlier summary that
also surfaces container waiting reasons like CrashLoopBackOff - which is why you see values
there that aren't phases.
Why does my pod alternate between Error and CrashLoopBackOff?
Same failure, two moments. Error is the instant the container exits non-zero;
CrashLoopBackOff is the backoff wait before the next restart. Diagnose it as one problem:
kubectl logs --previous.
How do I see why a pod has a given status?
kubectl describe pod <pod> and read from the bottom: Events, then the container's
State/Last State blocks, which carry the reason and exit code.
Is there a single command to triage everything at once?
kubectl get pods -o wide for the overview, then kubectl get events --sort-by=.lastTimestamp -n <namespace> - the sorted event stream is the closest thing to a
cluster-wide narration of what went wrong, in order.