hashicorp/nomad · error

volume name %q cannot be a reserved word for Windows filenam

Error message

volume name %q cannot be a reserved word for Windows filenames

What it means

When a Windows bind spec's destination looks like a named volume (a bare name, no path separator), the parser checks it against Windows reserved filenames (CON, PRN, AUX, NUL, COM1..9, LPT1..9). A reserved word is an illegal volume name on Windows, so the spec is rejected before any filesystem access.

Source

Thrown at drivers/docker/win32_volume_parse.go:140

			split = append(split, destination)
		}
	}
	if mode, exists := matchgroups["mode"]; exists {
		if mode != "" {
			split = append(split, mode)
		}
	}
	// Fix #26329. If the destination appears to be a file, and the source is null,
	// it may be because we've fallen through the possible naming regex and hit a
	// situation where the user intention was to map a file into a container through
	// a local volume, but this is not supported by the platform.
	if matchgroups["source"] == "" && matchgroups["destination"] != "" {
		volExp := regexp.MustCompile(`^` + rxName + `$`)
		reservedNameExp := regexp.MustCompile(`^` + rxReservedNames + `$`)

		if volExp.MatchString(matchgroups["destination"]) {
			if reservedNameExp.MatchString(matchgroups["destination"]) {
				return nil, fmt.Errorf("volume name %q cannot be a reserved word for Windows filenames", matchgroups["destination"])
			}
		} else {

			exists, isDir, _ := currentFileInfoProvider.fileInfo(matchgroups["destination"])
			if exists && !isDir {
				return nil, fmt.Errorf("file '%s' cannot be mapped. Only directories can be mapped on this platform", matchgroups["destination"])

			}
		}
	}
	return split, nil
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Rename the volume to a non-resident name (e.g. "mydata" instead of "CON").
  2. If you meant a host path, add separators/drive letter so it isn't treated as a volume name.
  3. Check against the Windows reserved list: CON, PRN, AUX, NUL, COM1-9, LPT1-9.

Example fix

// before
volumes = ["NUL:C:/data"]
// after
volumes = ["appdata:C:/data"]
Defensive patterns

Strategy: validation

Validate before calling

var reserved = map[string]bool{"CON": true, "PRN": true, "AUX": true, "NUL": true,
  "COM1": true, "COM2": true, "COM3": true, "COM4": true, "COM5": true, "COM6": true, "COM7": true, "COM8": true, "COM9": true,
  "LPT1": true, "LPT2": true, "LPT3": true, "LPT4": true, "LPT5": true, "LPT6": true, "LPT7": true, "LPT8": true, "LPT9": true}
if reserved[strings.ToUpper(volumeName)] {
  return fmt.Errorf("volume name %s is reserved on Windows", volumeName)
}

Try / catch

if err := validateVolumeName(name); err != nil {
  return fmt.Errorf("rename volume in jobspec: %w", err)
}

Prevention

When it happens

Trigger: windowsSplitRawSpec with a spec like "CON:C:\dest" or "nul:/data" where the source/destination matches rxName but also rxReservedNames.

Common situations: Volume names chosen carelessly in jobspecs (e.g. testing with "NUL"), or a short token that accidentally equals a reserved device name.

Related errors


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