jdx/mise · error
invalid tool version
Error message
invalid tool version {s:?}: contains forbidden character {c:?} What it means
mise enforces an allowlist of characters in version strings via is_forbidden_version_char. Any version containing a forbidden character (characters that could break shell commands, paths, or backend argument construction) is rejected with this message naming the offending character.
Solutions
- Remove or replace the flagged character with an allowed one (check the reported character in the message).
- Quote variables in shell scripts and trim input: mise install "foo@${VER// /}".
- If the value is not a version, use the correct prefix (ref:, tag:, path:), which has its own validation.
Example fix
// before (script) mise install node@$VERSION # VERSION="20.x beta" // after VERSION="20.11.0"; mise install "node@$VERSION"
Defensive patterns
Strategy: validation
Validate before calling
function validVersion(v) {
return typeof v === 'string' && !v.startsWith('-') && !v.includes('..') && !/[\s'";$|&`<>]/.test(v);
} Prevention
- Quote all interpolated values in shell scripts building mise commands.
- Trim templated outputs (no trailing newline/space) before writing configs.
- Restrict versions to [A-Za-z0-9._+~-] minus a leading dash.
When it happens
Trigger: ToolRequest::new_with_options receiving a version containing a character rejected by is_forbidden_version_char — e.g. spaces, quotes, '$', ';', '|', '&', backticks, newlines.
Common situations: Unquoted shell interpolation carrying whitespace or shell metacharacters into `mise install foo@...`; YAML/TOML values with trailing spaces; pasted versions with invisible characters or trailing newline.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- invalid tool path : contains forbidden character
- invalid tool ref : contains forbidden character
- invalid tool version
- action prediction payload is too large
- brew-cask: invalid command_wrapper environment name
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/6ca5f0679d17dd8b.
Report an issue: GitHub.
Appendix: source
Thrown at src/toolset/tool_request.rs:724
/// characters (newlines split shell tokens) and `..` (filesystem traversal).
/// Everything else is allowed so legitimate version vocabulary (npm-style
/// semver ranges like `>=20 <21 || >=22` or `^1.0.0`, dates, channel names,
/// `lts/hydrogen`, etc.) continues to work — those characters are only
/// dangerous in *unquoted* shell context, which cannot occur without one of
/// the rejected expansion characters appearing first. Leading dashes are also
/// rejected so backend install tools cannot mistake a version for a CLI flag.
fn validate_version_string(s: &str) -> Result<()> {
if s.is_empty() {
return Ok(());
}
if s.starts_with('-') {
bail!("invalid tool version {s:?}: must not start with '-'");
}
if s.contains("..") {
bail!("invalid tool version {s:?}: contains path-traversal sequence");
}
if let Some(c) = s.chars().find(|c| is_forbidden_version_char(*c)) {
bail!("invalid tool version {s:?}: contains forbidden character {c:?}");
}
Ok(())
}
/// Validate `ref:`/`branch:`/`tag:`/`rev:` values. Same character rules as
/// version strings: branch/tag names already use the same broad vocabulary
/// (`/`, `+`, `-`, etc.), so only shell-quote-breaking characters and leading
/// dashes need rejection. Kept as a separate function for distinct error
/// messages.
fn validate_ref_string(s: &str) -> Result<()> {
if s.is_empty() {
return Ok(());
}
if s.starts_with('-') {
bail!("invalid tool ref {s:?}: must not start with '-'");
}
if s.contains("..") {
bail!("invalid tool ref {s:?}: contains path-traversal sequence");View on GitHub (pinned to 533346cc37)