hashicorp/nomad · error

unable to pull docker image %q: %w

Error message

unable to pull docker image %q: %w

What it means

pullImageImpl first parses the image reference (repo/tag) before contacting the registry; a malformed reference is wrapped as "unable to pull docker image %q". Later pull failures with other causes are also wrapped by this same message via the pull flow, so it generally means the image could not be pulled, starting with reference parsing.

Source

Thrown at drivers/docker/coordinator.go:193

	// Nomad).
	delete(d.pullFutures, image)

	// If we are cleaning up, we increment the reference count on the image
	if err == nil && d.cleanup {
		d.incrementImageReferenceImpl(id, image, callerID)
	}

	return id, user, err
}

// pullImageImpl is the implementation of pulling an image.
func (d *dockerCoordinator) pullImageImpl(imageID string, authOptions *registry.AuthConfig,
	pullTimeout, pullActivityTimeout time.Duration) (string, string, error) {
	defer d.clearPullLogger(imageID)
	// Parse the repo and tag
	repo, tag, err := parseDockerImage(imageID)
	if err != nil {
		return "", "", fmt.Errorf("unable to pull docker image %q: %w", imageID, err)
	}

	pullCtx, cancel := context.WithTimeout(d.ctx, pullTimeout)
	pm := newImageProgressManager(imageID, cancel, pullActivityTimeout, d.handlePullInactivity,
		d.handlePullProgressReport, d.handleSlowPullProgressReport)
	defer pm.stop()

	// Attempt to pull the image
	var auth registry.AuthConfig
	if authOptions != nil {
		auth = *authOptions
	}

	pullOptions := mclient.ImagePullOptions{RegistryAuth: auth.Auth}
	reader, err := d.client.ImagePull(pullCtx, dockerImageRef(repo, tag), pullOptions)

	if errors.Is(err, context.DeadlineExceeded) {
		d.logger.Error("timeout pulling container", "image_ref", dockerImageRef(repo, tag))

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Fix the image reference: use 'name:tag' or 'name@sha256:digest' with valid characters (lowercase repo, no spaces).
  2. Add an explicit tag — avoid relying on implicit defaults or trailing colons.
  3. If the parse is fine but the pull itself failed, read the wrapped cause: check registry reachability, auth credentials, and image existence.
  4. Test the same reference locally with 'docker pull <ref>' to confirm it resolves.

Example fix

// before (job HCL)
config {
  image = "redis::7"
}
// after
config {
  image = "redis:7"
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate image reference before submitting the job
ok := regexp.MustCompile(`^[a-z0-9]+((\.|_|__|-)[a-z0-9]+)*(:[0-9]+)?(/[a-z0-9]+((\.|_|__|-)[a-z0-9]+)*)*(:[\w][\w.-]{0,127})?(@sha256:[a-f0-9]{64})?$`).MatchString(image)
if !ok { return fmt.Errorf("invalid image reference %q", image) }

Try / catch

Catch the pull error and inspect the wrapped cause with errors.Unwrap/errors.Is before deciding to retry.

Prevention

When it happens

Trigger: Requesting a pull with an imageID like 'library/redis:' (empty tag), invalid characters/whitespace, or a reference parseDockerImage cannot split into repo:tag.

Common situations: Template mistakes in job spec 'image' field (double colons 'redis::7', trailing colon, spaces), missing registry prefix where required, or invalid digest format.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/47b5a56fe28668fe. Report an issue: GitHub.