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

  1. Verify the image reference (registry/repo:tag) is correct and the tag actually exists (docker pull or curl the registry).
  2. Create/attach imagePullSecrets: kubectl create secret docker-registry regcred ... and reference it in the pod spec.
  3. Fix registry auth on the node (~/.docker/config.json, credential helpers, or node-level mirror config).
  4. 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

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


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/a3158f51fc1f5381. Report an issue: GitHub.