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 not

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Remove the \\?\ prefix and reference the directory with a normal absolute path (`path:C:/tools/dir` or `path:C:\tools\dir`).
  2. Shorten the path (or use a junction/subst drive) so the extended-length prefix is unnecessary.
  3. 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

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


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/e3abcb2872ff2666. Report an issue: GitHub.