jdx/mise · error
invalid tool path {s:?}: extended-length and device paths (\
Error message
invalid tool path {s:?}: extended-length and device paths (\\?\, \\.\) are not supported What it means
validate_path_string validates `path:` tool values. On Windows, the only backslash surviving the '\'→'/' rewrite is an extended-length (\\?\) or device (\\.\) prefix, so this arm reports those prefixes as unsupported rather than blaming an unfixable character. mise throws this during ToolRequest construction.
Source
Thrown at src/toolset/tool_request.rs:687
/// The list is written for a POSIX shell, which is why `\` is on it. On Windows `\` is a path
/// separator instead, so it is rewritten by [`windows_path_separators`] before it gets here rather
/// than being allowed through — see that function. The shell those hooks run through there is
/// `cmd.exe`, whose metacharacters are a different set, so a few more are rejected on Windows —
/// see [`is_forbidden_path_char`].
fn validate_path_string(s: &str) -> Result<()> {
if s.is_empty() {
return Ok(());
}
if let Some(c) = s.chars().find(|c| {
// Allow newlines/tabs/etc. in paths is still bad — keep control-char
// and quote/expansion rejection, but allow `/` since paths need it.
is_forbidden_path_char(*c)
}) {
// The only `\` that survives the rewrite is an extended-length or device prefix, so say
// what is actually wrong instead of naming a character the user cannot avoid.
#[cfg(windows)]
if c == '\\' {
bail!(
"invalid tool path {s:?}: extended-length and device paths (\\\\?\\, \\\\.\\) are not supported"
);
}
bail!("invalid tool path {s:?}: contains forbidden character {c:?}");
}
Ok(())
}
/// Rewrite `\` to `/` in a `path:` value on Windows.
///
/// `\` is the path separator there, not a shell metacharacter, so [`validate_path_string`] used to
/// reject every native path — anything copied out of Explorer or printed by `pwd`. Win32 accepts
/// `/` wherever it accepts `\`, so rewriting is what makes those usable *without* letting a `\`
/// reach a vfox hook's `ctx.rootPath`, which is the thing the list exists to prevent (#9814). The
/// alternative — dropping `\` from the list on Windows — would have weakened that.
///
/// Extended-length and device prefixes (`\\?\`, `\\.\`) are left alone. Those are the one place
/// Windows does not accept `/`, so rewriting would hand back a path that looks right and does notView on GitHub (pinned to afd2eddd3a)
Solutions
- Remove the \\?\ prefix and reference the directory with a normal absolute path (`path:C:/tools/dir` or `path:C:\tools\dir`).
- Shorten the path (or use a junction/subst drive) so the extended-length prefix is unnecessary.
- Avoid device paths (\\.\) — mise cannot treat them as a tool source; point at a real filesystem directory instead.
Example fix
// before (Windows mise.toml) [tools] "path:C:\\?\\C:\\very\\long\\path\\tools" = "1" // after [tools] "path:C:\\tools" = "1"
Defensive patterns
Strategy: validation
Validate before calling
function isPlainWindowsPath(p) {
return typeof p === 'string' && !p.startsWith('\\\\?\\') && !p.startsWith('\\\\.\\');
}
if (!isPlainWindowsPath(p)) throw new Error('extended-length/device paths are not supported'); Type guard
function isNormalPath(v) { return typeof v === 'string' && !/^\\\\[?.]\\/.test(v); } Prevention
- Strip \\?\ prefixes when copying paths from Windows APIs or long-path tooling.
- Keep tool directories under a short path to avoid needing extended-length syntax.
- Never reference device paths (\\.\) as tool sources.
When it happens
Trigger: On Windows, a tool entry like `"path:C:\\?\\C:\\huge\\dir"` or `path:\\.\\device...` in mise.toml/.tool-versions or on the CLI.
Common situations: Users copying paths from Windows tooling that returns extended-length paths for long directories, or referencing device paths for drives/devices that mise cannot install tools from.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- windows_script_interpreter: {interpreter:?} must be a plain
- Windows script file name {filename:?} contains unsupported c
- {target_raw}: target must be absolute or start with ~/
- cannot replace task stub directory because {} is not a gener
- Directory specified with --cd does not exist: {} Please chec
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/e3abcb2872ff2666.
Report an issue: GitHub.