hashicorp/nomad · error

file ' ' cannot be mapped. Only directories can be mapped…

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.

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.

Appendix: 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)