GoogleContainerTools/skaffold · error
creating container for %v: %v
Error message
creating container for %v: %v
What it means
CheckIfPullImgErr inspects a pod's container statuses and, when a container is stuck in a Waiting state whose reason is an image-pull error (ImagePullBackOff/ErrImagePull), returns this error naming the job. It surfaces Kubernetes' own pull failure as a Go error so callers can abort quickly instead of waiting for logs that will never arrive.
Source
Thrown at pkg/skaffold/k8sjob/util.go:194
return true, err
})
}
func isRetryableErr(k8sErr error) bool {
isRetryable := false
for _, checkIsRetryableErr := range retryableErrChecks {
isRetryable = isRetryable || checkIsRetryableErr(k8sErr)
}
return isRetryable
}
func CheckIfPullImgErr(pod *corev1.Pod, jobName string) error {
for _, cs := range pod.Status.ContainerStatuses {
if cs.State.Waiting == nil {
continue
}
if checkIsPullImgErr(cs.State.Waiting.Reason) {
return fmt.Errorf("creating container for %v: %v", jobName, cs.State.Waiting.Reason)
}
}
return nil
}
func checkIsPullImgErr(waitingReason string) bool {
return validator.ImagePullBackOff == waitingReason ||
validator.ErrImagePullBackOff == waitingReason ||
validator.ImagePullErr == waitingReason
}
View on GitHub (pinned to a1189de023)
Solutions
- Verify the image exists: `docker pull <image>` locally or check the registry; fix the tag/name in the job manifest
- Attach registry credentials: create a secret and set imagePullSecrets on the pod/job spec
- If using a local image with kind/minikube, load it into the cluster (kind load docker-image / minikube image load) instead of expecting a pull
- Check `kubectl describe pod` events to confirm ImagePullBackOff and the exact registry error
- Handle registry rate limits by authenticating or using a mirror
Example fix
// before image: myrepo/myimage:latst // after image: myrepo/myimage:latest # plus, for private registries: imagePullSecrets: - name: regcred
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate the image exists before applying the job
ref, _ := reference.ParseNormalizedNamed(imageTag)
// ensure tag is not :latest-accidental and image was pushed:
out, err := exec.Command("docker", "manifest", "inspect", imageTag).CombinedOutput()
if err != nil {
return fmt.Errorf("image %s not found in registry: %s", imageTag, out)
} Type guard
func hasPullErr(pod *corev1.Pod) (string, bool) {
for _, cs := range pod.Status.ContainerStatuses {
if cs.State.Waiting != nil &&
(cs.State.Waiting.Reason == "ImagePullBackOff" || cs.State.Waiting.Reason == "ErrImagePull") {
return cs.State.Waiting.Reason, true
}
}
return "", false
} Try / catch
if err := k8sjob.CheckIfPullImgErr(pod, jobName); err != nil {
// image-pull failure is terminal; don't retry blind
return fmt.Errorf("aborting: %w (check imagePullSecrets and tag)", err)
} Prevention
- Always pin exact image tags; never rely on a tag that may not exist
- Configure imagePullSecrets for private registries in every namespace the job runs in
- Pre-load local images into kind/minikube clusters before running jobs
- Watch pod events (kubectl describe pod) during development to catch pull failures early
When it happens
Trigger: A pod for the job has containerStatuses[].state.waiting.reason matching a pull-image error — wrong/misspelled image name or tag, private registry requiring credentials not present in the cluster, or the image does not exist in the registry.
Common situations: Pushing to a registry the cluster can't authenticate to (missing imagePullSecrets), typo'd image tag, referencing a locally-built image never pushed to the cluster, rate limiting from Docker Hub.
Related errors
- STATUSCHECK_IMAGE_PULL_ERR
- failed to execute container %s hook %d for artifact %q: %w
- c.Message (pod status condition message)
- unable to lookup minikube executable. Please add it to PATH
- invalid local-registry-hosting ConfigMap
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/b0b1422e3a2d3945.
Report an issue: GitHub.