hashicorp/nomad · error
Failed to pull `%s`: %w
Error message
Failed to pull `%s`: %w
What it means
recoverablePullError wraps any error from the Docker image pull as "Failed to pull `<image>`", marking it recoverable unless the error text matches the imageNotFoundMatcher (e.g. manifest unknown / not found), in which case retrying is pointless. Callers use the recoverable flag to decide whether to reschedule the allocation.
Source
Thrown at drivers/docker/coordinator.go:429
func (d *dockerCoordinator) handlePullProgressReport(image, msg string, _ time.Time) {
d.logger.Debug("image pull progress", "image_name", image, "message", msg)
}
func (d *dockerCoordinator) handleSlowPullProgressReport(image, msg string, _ time.Time) {
d.emitEvent(image, fmt.Sprintf("Docker image pull progress: %s", msg), map[string]string{
"image": image,
})
}
// recoverablePullError wraps the error gotten when trying to pull and image if
// the error is recoverable.
func recoverablePullError(err error, image string) error {
recoverable := true
if imageNotFoundMatcher.MatchString(err.Error()) {
recoverable = false
}
return structs.NewRecoverableError(fmt.Errorf("Failed to pull `%s`: %w", image, err), recoverable)
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Read the wrapped cause: if 'not found'/'manifest unknown', fix the image name/tag — retrying will not help.
- If recoverable (network/rate limit), configure registry auth (auth block or docker config) and check registry connectivity.
- Add registry credentials for private repos or authenticated Hub pulls to avoid rate limits.
- Verify DNS/proxy/firewall allows the node to reach the registry endpoint.
- Retry later for transient 5xx/timeout causes; Nomad will reschedule recoverable failures.
Example fix
// before (job HCL, private registry)
config { image = "mycorp/app:latest" }
// after
config { image = "mycorp/app:1.4.2" }
auth {
username = "ci-user"
password = "..."
server_address = "https://registry.mycorp.example"
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check image exists before submit
cli, _ := client.NewClientWithOpts(client.FromEnv)
if _, err := cli.DistributionInspect(ctx, image, authToken); err != nil {
return fmt.Errorf("image %q not resolvable in registry: %w", image, err)
} Type guard
func isNonRecoverablePull(err error) bool {
var re *structs.RecoverableError
if errors.As(err, &re) { return !re.IsRecoverable() }
return false
} Try / catch
err := pull(...)
var re *structs.RecoverableError
if errors.As(err, &re) && !re.IsRecoverable() {
return fmt.Errorf("bad image name/tag, not retrying: %w", err)
}
// otherwise backoff + retry Prevention
- Configure registry auth for private repos and authenticated Docker Hub pulls.
- Pin concrete tags (not :latest) to avoid surprise not-found/manifest errors.
- Monitor Docker Hub rate limits; add a mirror or paid plan.
- Check structs.NewRecoverableError flag to decide retry vs fail-fast.
When it happens
Trigger: Any pullImageImpl failure reaching this wrapper: registry unreachable, auth rejected, rate limited, network timeouts, or image truly nonexistent in the registry.
Common situations: Docker Hub rate limiting (429 toomanyrequests), missing/misconfigured registry auth for a private repo, wrong image name (typo causing 'not found' -> non-recoverable), corporate proxy blocking registry.default
Related errors
- wait aborted: %w
- unable to pull docker image %q: %w
- %s %s: %s
- Failed to find docker auth for repo %q: %v
- Failed to inspect container %s: %s
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/dbd33de57b052c89.
Report an issue: GitHub.