jdx/mise · error
returned an unsafe absolute path
Error message
{kind} returned an unsafe absolute path: {path:?} What it means
After running a remote helper command that must yield an absolute filesystem path (kind names which, e.g. install path or mise path), mise strips the trailing newline and validates it: it must start with '/', and contain no NUL, newline, or carriage-return bytes. Any other output means the remote command misbehaved, so mise rejects it with this error instead of using an unsafe path.
Solutions
- Make the remote command print only the absolute path to stdout (send diagnostics to stderr)
- Verify the remote filesystem layout so the command resolves a real absolute path
- Fix or remove ssh wrappers/rc-files that inject CR characters or extra lines into output
Example fix
// before echo "installing..."; echo "$PREFIX/bin/mise" // two lines -> rejected // after echo "installing..." >&2; printf '%s\n' "$PREFIX/bin/mise"
Defensive patterns
Strategy: validation
Validate before calling
function isValidAbsoluteRemotePathOutput(s) {
const p = s.endsWith('\n') ? s.slice(0, -1) : s;
return p.startsWith('/') && !/[\0\n\r]/.test(p);
} Type guard
const isAbsolutePath = (s: unknown): s is string =>
typeof s === 'string' && s.startsWith('/') && !/[\0\n\r]/.test(s); Try / catch
match validated_absolute_remote_path_output(out, kind) {
Ok(path) => use(path),
Err(e) => { log_raw_output(out); return Err(e); }
} Prevention
- Remote path-emitting commands must write only the final path to stdout
- Strip ANSI codes and banners from remote scripts' stdout
- Beware CRLF-producing remotes; normalize line endings upstream
- Test helpers with `set -e` and clean environments
When it happens
Trigger: A remote command whose stdout is expected to be a single absolute path returns a relative path, an empty/blank line, extra output lines, or text containing CR/LF/NUL (e.g. a script that logs progress to stdout).
Common situations: Remote install scripts printing progress to stdout alongside the final path; Windows/MSYS output with CRLF line endings after an incomplete newline strip; helper aliases resolving to relative paths.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- bootstrap_command returned an unsafe mise path
- remote host ' ' bootstrap command contains NUL
- a provided source resolves to a path
- a validated copy_link has a staged parent
- brew-cask: command_wrapper requires a command name without…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/180d90e08738c53d.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/remote.rs:2208
}
Ok(())
}
fn validated_remote_command(command: &str) -> Result<String> {
if !command.starts_with('/') || command.contains(['\0', '\n', '\r']) {
bail!("bootstrap_command returned an unsafe mise path: {command:?}");
}
Ok(command.to_string())
}
fn validated_remote_command_output(output: &str) -> Result<String> {
validated_remote_command(output.strip_suffix('\n').unwrap_or(output))
}
fn validated_absolute_remote_path_output(output: &str, kind: &str) -> Result<String> {
let path = output.strip_suffix('\n').unwrap_or(output);
if !path.starts_with('/') || path.contains(['\0', '\n', '\r']) {
bail!("{kind} returned an unsafe absolute path: {path:?}");
}
Ok(path.to_string())
}
fn validate_install_mise_path(path: &str) -> Result<()> {
validate_value("mise install path", path)?;
if path.contains(['\n', '\r']) {
bail!("install_mise must not contain a newline: {path:?}");
}
if !path.starts_with('/') && !path.starts_with("~/") {
bail!("install_mise must be an absolute path or start with ~/: {path:?}");
}
if path.split('/').any(|component| component == "..") {
bail!("install_mise must not contain '..': {path:?}");
}
if matches!(
path.rsplit('/').next(),
None | Some("") | Some(".") | Some("~")View on GitHub (pinned to 533346cc37)