jdx/mise · error
invalid tool ref : must not start with
Error message
invalid tool ref {s:?}: must not start with '-' What it means
Values given via ref:/branch:/tag:/rev: prefixes are validated with validate_ref_string. A ref starting with '-' is rejected so git/backend invocations cannot mistake the ref for a command-line flag. Empty refs are permitted; dash-prefixed ones are not.
Solutions
- Remove the leading dash and give a plain ref name (ref:main, tag:v1.2).
- If the dash is part of a git option you want, restructure: mise does not accept git flags in ref values.
- Check scripts that build ref strings from variables for accidental flag leakage.
Example fix
// mise.toml before
node = { version = "ref:-b main" }
// after
node = { version = "ref:main" } Defensive patterns
Strategy: validation
Validate before calling
function validRef(r) {
return typeof r === 'string' && (r === '' || !r.startsWith('-'));
} Prevention
- Store plain ref names (branch/tag/SHA), never git flags.
- Review generated mise.toml for leading dashes in ref fields.
- Copy refs from `git branch --format=%(refname:short)` not from command lines.
When it happens
Trigger: Calling new_with_options with a ref value like ref:-b branch, or config entries such as `tool = { version = 'ref:-x' }` where the ref begins with '-'.
Common situations: Copy-pasting git command fragments (-b main) into a ref value; scripts interpolating flags into the ref position; typos in mise.toml tool entries.
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.
Related errors
- invalid tool ref : contains forbidden character
- invalid tool version
- a repository preview directory requires a dry run
- action prediction payload is too large
- `--all` needs `--to
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/dd3b3ff74e1221ba.
Report an issue: GitHub.
Appendix: source
Thrown at src/toolset/tool_request.rs:739
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");
}
if let Some(c) = s.chars().find(|c| is_forbidden_version_char(*c)) {
bail!("invalid tool ref {s:?}: contains forbidden character {c:?}");
}
Ok(())
}
/// Validate `path:` values. Filesystem paths legitimately contain `/`, spaces,
/// and many other characters, but the resolved path becomes `ctx.rootPath` /
/// `installPath` for path-mode tools and is interpolated into shell commands
/// by some plugin hooks. Reject the same shell-quote-breaking characters as
/// version strings — `$`, backtick, quotes, and `\` — so a hostile `path:`
/// entry in a project config cannot inject shell syntax. Path traversal is
/// intentionally not rejected here because `path:../tools/foo` is a normal
/// relative-path use case.View on GitHub (pinned to 533346cc37)