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
- Use a bare executable name that is on PATH, e.g. `windows_script_interpreter = "python"` or `"node.exe"`
- Put the interpreter's directory on PATH (user/system env, or via mise env) instead of specifying a path
- 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
- Use bare interpreter names (python, node.exe) and put their dirs on PATH
- Never put paths or CLI flags in windows_script_interpreter
- Pass interpreter flags inside the script, not the config
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
- Windows script file name {filename:?} contains unsupported c
- mise prune --monorepo is not implemented yet
- mise upgrade --monorepo is not implemented yet
- trimSuffix requires exactly 2 arguments
- invalid Cargo crate name: {name:?}
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/dac1bb13b7d9253e.
Report an issue: GitHub.