jdx/mise · error · eyre::Report

windows_script_interpreter: {interpreter:?} must be a plain

Error message

windows_script_interpreter: {interpreter:?} must be a plain executable name

What it means

On Windows, the http backend can generate a .cmd launcher that invokes a downloaded script through the configured `windows_script_interpreter`. Because the interpreter string is interpolated directly into a batch file body (`@echo off ... {interpreter} ...`), it must be a plain executable name — non-empty, ASCII alphanumeric plus `.`, `_`, `-` only. Paths, arguments, spaces, or shell metacharacters would enable command injection or broken launchers, so they are rejected.

Source

Thrown at src/backend/http.rs:995

            );
            return None;
        }
        let file_algo = crate::backend::asset_matcher::detect_checksum_algorithm(
            &get_filename_from_url(&checksum_url),
        );
        fetch_checksum_from_file(&checksum_url, &file_algo).await
    }
}

#[cfg(any(windows, test))]
fn windows_script_launcher(script: &Path, interpreter: &str) -> Result<(PathBuf, String)> {
    ensure_plain_bin_name("windows_script_interpreter", interpreter)?;
    if interpreter.is_empty()
        || !interpreter
            .chars()
            .all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '.' | '_' | '-'))
    {
        eyre::bail!("windows_script_interpreter: {interpreter:?} must be a plain executable name");
    }
    let filename = script
        .file_name()
        .and_then(|filename| filename.to_str())
        .ok_or_else(|| eyre::eyre!("Windows script launcher requires a UTF-8 file name"))?;
    ensure_plain_bin_name("windows script", filename)?;
    if filename.is_empty()
        || !filename
            .chars()
            .all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '.' | '_' | '-'))
    {
        eyre::bail!("Windows script file name {filename:?} contains unsupported characters");
    }
    let launcher = script.with_file_name(format!("{filename}.cmd"));
    let body = format!("@echo off\r\n{interpreter} \"%~dp0{filename}\" %*\r\n");
    Ok((launcher, body))
}

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Use a bare executable name that is on PATH, e.g. `windows_script_interpreter = "python"` or `"node.exe"`
  2. Put the interpreter's directory on PATH (user/system env, or via mise env) instead of specifying a path
  3. Pass flags via the script itself, not through the interpreter string

Example fix

# before (mise.toml)
[tools."http://example.com/tool.py"]
windows_script_interpreter = 'C:\\Python311\\python.exe'
# after
[tools."http://example.com/tool.py"]
windows_script_interpreter = "python"
Defensive patterns

Strategy: validation

Validate before calling

# windows config gate: interpreter must be a bare name
[[ "$interp" =~ ^[A-Za-z0-9._-]+$ ]] || echo 'use a plain executable name like python'

Prevention

When it happens

Trigger: A Windows install of an http: tool whose options set `windows_script_interpreter` to something like `C:\\Python\\python.exe`, `python -u`, `node --experimental-vm-modules`, or any string with slashes/spaces — windows_script_launcher() rejects it before writing the launcher.

Common situations: Users copying an interpreter path from other tooling config into mise; trying to pass interpreter flags; portable installs where the interpreter is not on PATH so a full path 'seems' necessary.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/dac1bb13b7d9253e. Report an issue: GitHub.