jdx/mise · error
invalid tool version {s:?}: contains forbidden character {c:
Error message
invalid tool version {s:?}: contains forbidden character {c:?} What it means
validate_version_string rejects tool version strings that start with '-', contain '..' (path traversal), or contain any character matched by is_forbidden_version_char. mise throws this during ToolRequest construction (new_with_options) to prevent flag injection and path-traversal via tool versions. The message names the exact offending character.
Source
Thrown at src/toolset/tool_request.rs:634
/// 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 afd2eddd3a)
Solutions
- Inspect the error for the quoted forbidden character and remove/escape it from the version string in your config or CLI argument.
- Quote shell variables to avoid stray whitespace: `mise use node@"$VER"`.
- If you need a ref-like value (branch/tag/rev), use the proper prefix (`ref:`, `tag:`, `branch:`) rather than embedding it in a plain version.
Example fix
// before (mise.toml) node = "1.2.3 beta" // after node = "1.2.3"
Defensive patterns
Strategy: validation
Validate before calling
function isValidToolVersion(v) {
return typeof v === 'string' && v.length > 0 && !v.startsWith('-') &&
!v.includes('..') && !/[^A-Za-z0-9._+:@\/-]/.test(v);
}
if (!isValidToolVersion(ver)) throw new Error(`bad version: ${ver}`); Type guard
function isSafeVersion(v) { return typeof v === 'string' && /^v?\d[\w.+-]*$/.test(v); } Prevention
- Quote shell variables used in version slots to prevent whitespace/metachar injection.
- Keep versions in mise.toml rather than composing them dynamically in scripts.
- Sanitize any user/CI-supplied version before passing it to mise.
When it happens
Trigger: Calling mise with a version string like `node@--foo`, `node@../../etc`, or containing characters such as shell metacharacters, whitespace, or other disallowed symbols, e.g. `mise use node@1.2.3;rm`, or a malformed entry in .tool-versions/mise.toml.
Common situations: Typos in mise.toml or .tool-versions files, shell interpolation leaking spaces or semicolons into the version slot (`node@$VERSION extra`), copy-pasting a tag with a leading dash, or scripts building version strings from untrusted input.
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- invalid tool ref {s:?}: must not start with '-'
- brew-cask: invalid {kind} '{value}'
- {option}: '{name}' must be a plain file name (no path separa
- {option}: '{path}' must be a safe relative path (no absolute
- invalid prefix: {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/6ca5f0679d17dd8b.
Report an issue: GitHub.