hashicorp/nomad · error

unable to create local docker image %q: %w

Error message

unable to create local docker image %q: %w

What it means

createImage wraps any failure from parseDockerImage when splitting the task's docker image into repository and tag. It means the image string itself could not be parsed into a valid repo:tag reference before any registry interaction. The wrapped error typically indicates a malformed image reference (e.g. invalid characters or empty name).

Source

Thrown at drivers/docker/driver.go:625

		if attempted < 5 {
			attempted++
			backoff = helper.Backoff(50*time.Millisecond, time.Minute, attempted)
			time.Sleep(backoff)
			goto START
		}
		return nstructs.NewRecoverableError(startErr, true)
	}

	return recoverableErrTimeouts(startErr)
}

// createImage creates a docker image either by pulling it from a registry or by
// loading it from the file system
func (d *Driver) createImage(task *drivers.TaskConfig, driverConfig *TaskConfig, client *client.Client) (string, string, error) {
	image := driverConfig.Image
	repo, tag, err := parseDockerImage(image)
	if err != nil {
		return "", "", fmt.Errorf("unable to create local docker image %q: %w", image, err)
	}

	// We're going to check whether the image is already downloaded. If the tag
	// is "latest", or ForcePull is set, we have to check for a new version every time so we don't
	// bother to check and cache the id here. We'll download first, then cache.
	if driverConfig.ForcePull {
		d.logger.Debug("force pulling image instead of inspecting local", "image_ref", dockerImageRef(repo, tag))
	} else if tag != "latest" {
		if dockerImage, _ := client.ImageInspect(d.ctx, image); dockerImage.ID != "" {
			// Image exists so just increment its reference count
			d.coordinator.IncrementImageReference(dockerImage.ID, image, task.ID)
			var user string
			if dockerImage.Config != nil {
				user = dockerImage.Config.User
			}
			return dockerImage.ID, user, nil
		}
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Fix the image field in the task's driver config to a valid reference like 'nginx:1.25' or 'hashicorp/http-echo:0.2.1'.
  2. Check that any template/variable interpolation used to build the image name actually resolves (no empty values).
  3. If the image has no tag, add an explicit tag so parsing is unambiguous.
  4. Inspect the wrapped error (%w) in the job logs for the exact parse failure.

Example fix

// before
config {
  image = ""
}
// after
config {
  image = "nginx:1.25"
}
Defensive patterns

Strategy: validation

Validate before calling

func validImageRef(image string) bool {
	if image == "" { return false }
	parts := strings.Split(image, ":")
	if len(parts) > 2 { return false }
	if !strings.ContainsAny(parts[0], "/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_") { return false }
	return true
}
// call before submitting job: validImageRef(cfg.Image)

Prevention

When it happens

Trigger: driverConfig.Image contains a reference parseDockerImage rejects — e.g. an empty image string, invalid characters, or a ref that cannot be split into repo/tag. Raised synchronously in StartTask via createImage before any pull or load happens.

Common situations: Typos in the image field of the docker task driver config, template interpolation leaving image empty (e.g. missing variable), pasting a full 'docker pull' command line, or stray whitespace/quotes in the image name.

Related errors


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