GoogleContainerTools/skaffold · error
STATUSCHECK_IMAGE_PULL_ERR
STATUSCHECK_IMAGE_PULL_ERR
Error message
container %s is waiting to start: %s can't be pulled
What it means
Raised when a container's Waiting state has reason ImagePullBackOff or ErrImagePull (code STATUSCHECK_IMAGE_PULL_ERR): the kubelet cannot pull the container image, so the container can never start. The message names the container and its image.
Source
Thrown at pkg/diag/validator/validator.go:371
}
return fmt.Sprintf(actionableMessage, p.namespace, p.name)
}
func extractErrorMessageFromWaitingContainerStatus(po *v1.Pod, c v1.ContainerStatus) (proto.StatusCode, []string, error) {
// Extract meaning full error out of container statuses.
switch c.State.Waiting.Reason {
case podInitializing:
// container is waiting to run. This could be because one of the init containers is
// still not completed
return proto.StatusCode_STATUSCHECK_POD_INITIALIZING, nil, nil
case containerCreating:
return proto.StatusCode_STATUSCHECK_CONTAINER_CREATING, nil, fmt.Errorf("creating container %s", c.Name)
case crashLoopBackOff:
// TODO, in case of container restarting, return the original failure reason due to which container failed.
sc, l := getPodLogs(po, c.Name, proto.StatusCode_STATUSCHECK_CONTAINER_RESTARTING)
return sc, l, fmt.Errorf("container %s is backing off waiting to restart", c.Name)
case ImagePullErr, ImagePullBackOff, ErrImagePullBackOff:
return proto.StatusCode_STATUSCHECK_IMAGE_PULL_ERR, nil, fmt.Errorf("container %s is waiting to start: %s can't be pulled", c.Name, c.Image)
case runContainerError:
match := runContainerRe.FindStringSubmatch(c.State.Waiting.Message)
if len(match) != 0 {
return proto.StatusCode_STATUSCHECK_RUN_CONTAINER_ERR, nil, fmt.Errorf("container %s in error: %s", c.Name, trimSpace(match[3]))
}
}
log.Entry(context.TODO()).Debugf("Unknown waiting reason for container %q: %v", c.Name, c.State)
return proto.StatusCode_STATUSCHECK_CONTAINER_WAITING_UNKNOWN, nil, fmt.Errorf("container %s in error: %v", c.Name, c.State.Waiting)
}
func newPodStatus(n string, ns string, p string) *podStatus {
return &podStatus{
name: n,
namespace: ns,
phase: p,
ae: proto.ActionableErr{
ErrCode: proto.StatusCode_STATUSCHECK_SUCCESS,
},View on GitHub (pinned to a1189de023)
Solutions
- Verify the image reference (registry/repo:tag) is correct and the tag actually exists (docker pull or curl the registry).
- Create/attach imagePullSecrets: kubectl create secret docker-registry regcred ... and reference it in the pod spec.
- Fix registry auth on the node (~/.docker/config.json, credential helpers, or node-level mirror config).
- Check architecture/OS match (amd64 vs arm64) and, for rate limits, use a mirror or authenticated pulls.
Example fix
// before: private image without credentials
// image: gcr.io/my-proj/app:latest
// after: with secret attached
// imagePullSecrets: [{name: gcr-key}]
// image: gcr.io/my-proj/app:v1.2.3 Defensive patterns
Strategy: validation
Validate before calling
img := pod.Spec.Containers[0].Image; if err := registry.CheckImageExists(ctx, img, pullSecrets); err != nil { return fmt.Errorf("image %s not pullable: %w", img, err) } Type guard
func isImagePullError(cs v1.ContainerStatus) bool { r := cs.State.Waiting != nil && cs.State.Waiting.Reason; return r == "ImagePullBackOff" || r == "ErrImagePull" } Try / catch
sc, _, err := getContainerStatus(pod, cs); if sc == proto.StatusCode_STATUSCHECK_IMAGE_PULL_ERR { return fmt.Errorf("fix image ref/credentials for %s before retrying", cs.Name) } // do not blind-retry Prevention
- Pin digests or immutable tags; never rely on :latest in prod
- Attach imagePullSecrets to every service account that deploys
- Pre-pull or mirror images for air-gapped/restricted clusters
- Verify image architecture matches node (amd64/arm64)
When it happens
Trigger: extractErrorMessageFromWaitingContainerStatus matches ImagePullErr/ImagePullBackOff/ErrImagePullBackOff in the Waiting reason and returns 'container <name> is waiting to start: <image> can't be pulled'.
Common situations: Typo in image name/tag, private registry without imagePullSecrets, expired registry credentials, rate limiting (Docker Hub), image not present on air-gapped cluster, wrong architecture manifest.
Related errors
- creating container for %v: %v
- invalid local-registry-hosting ConfigMap
- failed to execute container %s hook %d for artifact %q: %w
- pulling init container image
- c.Message (pod status condition message)
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/a3158f51fc1f5381.
Report an issue: GitHub.