kubernetesseverity: blocker
ImagePullBackOff

Kubernetes: ImagePullBackOff — pod can't pull container image

ImagePullBackOff — pod can't pull image

95% fixable~15 mindifficulty: intermediate

Verified against Kubernetes docs: Images — ImagePullBackOff, kubelet source: pkg/kubelet/images/image_manager.go, Kubernetes docs: Pull an Image from a Private Registry · Updated June 2026

> quick_fix

The kubelet on the node can't pull your container image. Check three things in order: (1) the image name and tag are correct and exist in the registry, (2) the pod has imagePullSecrets for private registries, (3) the node has network access to the registry.

# See the exact error:
kubectl describe pod <pod-name> | grep -A 5 Events

# Check if image exists:
docker pull your-registry.com/app:tag

# Check imagePullSecrets:
kubectl get pod <pod-name> -o jsonpath='{.spec.imagePullSecrets}'

What causes this error

ImagePullBackOff is a pod status indicating the kubelet tried to pull the container image and failed. After the initial failure (ErrImagePull), Kubernetes applies an exponential backoff — waiting 10s, then 20s, then 40s, up to 5 minutes between retries. The 'BackOff' part means it's in this retry-wait cycle. Common root causes: typo in the image name or tag, the tag doesn't exist in the registry (e.g., 'latest' was never pushed), the registry requires authentication and imagePullSecrets are missing or wrong, or the node can't reach the registry network.

> advertisementAdSense placeholder

How to fix it

  1. 01

    step 1

    Get the exact failure reason

    kubectl describe pod gives you the specific error message from the kubelet. Look under Events for the 'Failed to pull image' message — it tells you exactly what went wrong.

    kubectl describe pod <pod-name> -n <namespace>
    # Look for: Failed to pull image "...": rpc error: ...
  2. 02

    step 2

    Verify the image exists

    Try pulling the exact image:tag from your local machine. If it fails locally, the image doesn't exist or the tag is wrong. Check your CI/CD pipeline to confirm the image was pushed successfully.

  3. 03

    step 3

    Check registry authentication

    For private registries, pods need an imagePullSecret. Create one if missing, then reference it in the pod spec.

    # Create a secret for Docker Hub / private registry:
    kubectl create secret docker-registry regcred \
      --docker-server=your-registry.com \
      --docker-username=user \
      --docker-password=pass \
      -n <namespace>
    
    # Add to pod spec:
    # imagePullSecrets:
    #   - name: regcred
  4. 04

    step 4

    Check node network access

    If the image exists and auth is correct, the node may not have network access to the registry. This is common in air-gapped clusters or when egress rules block registry traffic. SSH into the node and test: curl -I https://your-registry.com/v2/

How to verify the fix

  • kubectl get pod shows Running (not ImagePullBackOff).
  • kubectl describe pod shows 'Successfully pulled image' in Events.
  • The application inside the pod starts normally.

Why ImagePullBackOff happens at the runtime level

The kubelet on each node is responsible for pulling container images. When a pod is scheduled to a node, the kubelet's image manager (pkg/kubelet/images/image_manager.go) calls the container runtime (containerd/CRI-O) to pull the image. If the pull fails, the kubelet reports the failure to the API server, which updates the pod status to ErrImagePull. The backoff manager then applies exponential backoff (implemented in pkg/kubelet/images/image_manager.go's backOff field), delaying retries at 10s, 20s, 40s, up to 300s. During the backoff wait, the pod status shows ImagePullBackOff. The kubelet never stops retrying — the backoff caps at 5 minutes but continues indefinitely until the image is pullable or the pod is deleted.

Common debug mistakes for ImagePullBackOff

  • Assuming the image tag 'latest' is actually the latest push — 'latest' is just a tag name, not a guarantee. If your CI doesn't explicitly push with :latest, the tag may point to a months-old image or not exist at all.
  • Creating the imagePullSecret in the wrong namespace — secrets are namespace-scoped. A secret in 'default' won't be found by a pod in 'production'. Create the secret in the same namespace as the pod.
  • Forgetting that each node pulls independently — if your image works on one node but not another, the failing node may have different network access, a stale cache, or missing credentials.
  • Using docker login on the node instead of creating a Kubernetes secret — node-level Docker config works but doesn't scale and breaks when nodes are replaced. Always use imagePullSecrets for production.

When ImagePullBackOff signals a deeper problem

Recurring ImagePullBackOff across deployments usually means the image push and pod deployment are not properly sequenced in CI/CD. If the deployment manifest updates before the CI pipeline finishes pushing the new image, Kubernetes tries to pull a tag that doesn't exist yet. The fix is a CI/CD pipeline that: (1) builds and pushes the image, (2) verifies the image exists in the registry (digest check), (3) then and only then updates the Kubernetes deployment. Teams using GitOps (ArgoCD, Flux) should configure image update automation that triggers only on verified pushes, not on manifest commits.

Editor's take

The most time-consuming ImagePullBackOff I've debugged was in a corporate Kubernetes cluster behind an egress proxy. The image existed, the credentials were correct, but the node's containerd couldn't reach the registry because the HTTP_PROXY environment variable wasn't configured in containerd's systemd service file — only in the node's shell profile. The pod showed 'context deadline exceeded' in the pull error, which looked like a timeout but was actually a network block. It took 45 minutes to figure out that containerd and the node's shell have separate proxy configurations.

The insight that separates a Kubernetes beginner from an operator is understanding that image pulling is a node-level operation, not a cluster-level one. Each node pulls independently through its own container runtime. This means ImagePullBackOff can be node-specific: one node pulls fine (image cached, or has network access), while another fails. When debugging, always check which node the pod is scheduled on (kubectl get pod -o wide) and test from that specific node.

Adjacent errors: CrashLoopBackOff (image pulled successfully but the container keeps crashing), ErrImageNeverPull (imagePullPolicy: Never but image isn't cached on the node), and 'unauthorized: authentication required' (the imagePullSecret exists but the credentials are wrong or expired).

By Bikram Nath · Curator · Updated June 2026

Frequently asked questions

What's the difference between ErrImagePull and ImagePullBackOff?

ErrImagePull is the initial failure. ImagePullBackOff is the state after Kubernetes starts exponential backoff retries. They indicate the same problem — the backoff state just means Kubernetes has been retrying for a while.

How long does ImagePullBackOff retry?

Indefinitely. Kubernetes retries with exponential backoff (10s, 20s, 40s, 80s, 160s, capped at 5 minutes). It never gives up — the pod stays in ImagePullBackOff until the image becomes pullable or you delete the pod.

Does imagePullPolicy affect this?

Yes. imagePullPolicy: Always forces a pull every time. imagePullPolicy: IfNotPresent skips the pull if the image is already cached on the node. If you're seeing ImagePullBackOff with IfNotPresent, the image has never been successfully pulled to that specific node.

disclosure:Errordex runs AdSense, has zero third-party affiliate or sponsored links, and occasionally links to the editor’s own paid digital products (clearly labelled). Every fix is cross-referenced against the official sources listed in the “sources” sidebar before it ships. If a fix here didn’t work for you, please email so we can update the page.