jdx/mise · error
invalid tool path : extended-length and device paths (\\?\…
Error message
invalid tool path {s:?}: extended-length and device paths (\\?\, \\.\) are not supported What it means
On Windows, a path: tool value may not use extended-length (\\?\) or device (\\.\) path prefixes. Backslashes are rewritten to '/' and the only surviving '\' is such a prefix, so validate_path_string reports the prefix problem explicitly instead of a confusing forbidden-character message.
Solutions
- Strip the \\?\ or \\.\ prefix and use a plain absolute path, e.g. path:C:/tools/foo.
- Use forward slashes (mise rewrites them anyway) and avoid UNC device syntax.
- If the path exceeds MAX_PATH, use a short path (GetShortPathName) or a directory junction instead of the extended-length prefix.
Example fix
// mise.toml (Windows) before node = "path:\\\?\C:\tools\node" // after node = "path:C:/tools/node"
Defensive patterns
Strategy: validation
Validate before calling
function validPath(p) {
return typeof p === 'string' && !p.startsWith('\\\\?\\') && !p.startsWith('\\\\.\\');
} Prevention
- Strip \\?\ / \\.\ prefixes returned by Windows APIs before storing paths.
- Use forward slashes in mise.toml paths on Windows.
- Keep project directories shallow enough to avoid MAX_PATH issues.
When it happens
Trigger: On Windows, passing a path: value like \\?\C:\tools\foo or \\.\pipe\... through new_with_options; after backslash rewriting, the leading '\' characters remain and hit the windows-only bail.
Common situations: Copying a path obtained from Windows APIs (many return \\?\-prefixed paths) into mise.toml; long paths auto-normalized by other tooling; UNC/device paths pasted from PowerShell.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid tool path : contains forbidden character
- action prediction payload is too large
- bootstrap_command returned an unsafe mise path
- brew-cask: command_wrapper requires a command name without…
- brew-cask: invalid command_wrapper environment name
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/e3abcb2872ff2666.
Report an issue: GitHub.
Appendix: source
Thrown at src/toolset/tool_request.rs:777
/// 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 533346cc37)