hashicorp/nomad · error

not <src>:<destination> format

Error message

not <src>:<destination> format

What it means

On Windows, parseVolumeSpecWindows runs windowsSplitRawSpec (regex-based parser handling drive letters and UNC paths); if the regex split fails it rejects the bind spec because it doesn't look like <src>:<destination>. This is a fast-fail before any path existence checks.

Source

Thrown at drivers/docker/utils.go:300

	if filepath.IsAbs(dir) {
		return filepath.Clean(dir)
	}

	return filepath.Clean(filepath.Join(base, dir))
}

func parseVolumeSpec(volBind, os string) (hostPath string, containerPath string, mode string, err error) {
	if os == "windows" {
		return parseVolumeSpecWindows(volBind)
	}
	return parseVolumeSpecLinux(volBind)
}

func parseVolumeSpecWindows(volBind string) (hostPath string, containerPath string, mode string, err error) {
	parts, err := windowsSplitRawSpec(volBind, rxDestination)
	if err != nil {
		return "", "", "", fmt.Errorf("not <src>:<destination> format")
	}

	if len(parts) < 2 {
		return "", "", "", fmt.Errorf("not <src>:<destination> format")
	}

	// Convert host mount path separators to match the host OS's separator
	// so that relative paths are supported cross-platform regardless of
	// what slash is used in the jobspec.
	hostPath = filepath.FromSlash(parts[0])
	containerPath = parts[1]

	if len(parts) > 2 {
		mode = parts[2]
	}

	return
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Rewrite the volume string in absolute Windows form: "C:\host\path:C:\container\path".
  2. Remove spaces/quotes around the colon; each side must be a valid path.
  3. Avoid relative host paths on Windows; resolve to an absolute path in the jobspec.

Example fix

// before
volumes = ["./data:c:/data"]
// after
volumes = ["C:/nomad/data:C:/container/data"]
Defensive patterns

Strategy: validation

Validate before calling

func validWindowsBind(s string) bool {
  parts := strings.Split(s, ":")
  return len(parts) >= 2 && len(parts) <= 3 &&
    (filepath.IsAbs(parts[0]) || filepath.VolumeName(parts[0]) != "") &&
    parts[1] != ""
}

Try / catch

host, cont, mode, err := parseVolumeSpec(volBind)
if err != nil {
  return fmt.Errorf("volume %q rejected: %w", volBind, err)
}

Prevention

When it happens

Trigger: Passing a volBind string to parseVolumeSpec on Windows where windowsSplitRawSpec returns an error: unbalanced/absent colon, malformed path the rxDestination regex can't match (e.g. "C::data" or quoting artifacts).

Common situations: Jobspec volume stanzas written with Linux syntax on a Windows client (relative paths like "./data:/data"), stray spaces, or templates leaving empty segments.

Related errors


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