hashicorp/nomad · error

file '%s' cannot be mapped. Only directories can be mapped o

Error message

file '%s' cannot be mapped. Only directories can be mapped on this platform

What it means

Windows bind mounts only support directories, so when the destination token of a spec is an existing path on disk that is a file (not a directory), windowsSplitRawSpec rejects it. The existence check uses the injected fileInfoProvider before returning split parts.

Source

Thrown at drivers/docker/win32_volume_parse.go:146

		}
	}
	// 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. Mount the file's parent directory instead, or switch to copying the file into the image/template stanza.
  2. Create the destination as a directory (mkdir) before the job runs.
  3. If you intended a named volume, verify the token isn't colliding with an existing file of the same name.

Example fix

// before
volumes = ["C:/configs:C:/app/config.txt"]
// after
volumes = ["C:/configs:C:/app/configs"] // mount directory, deliver file via template
Defensive patterns

Strategy: validation

Validate before calling

if fi, err := os.Stat(destPath); err == nil && !fi.IsDir() {
  return fmt.Errorf("destination %s is a file; Windows mounts require directories", destPath)
}

Try / catch

if err := ensureDestIsDir(dest); err != nil {
  return fmt.Errorf("cannot mount: %w", err)
}

Prevention

When it happens

Trigger: Spec like "C:\host:C:\some\file.txt" where C:\some\file.txt exists and is a regular file; the parser refuses to map a file as a mount target on Windows.

Common situations: Mounting a single-file config (works on Linux bind mounts) into a container on a Windows host; destination path created as a file by a previous run instead of a directory.

Related errors


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