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

  1. Make the remote command print only the absolute path to stdout (send diagnostics to stderr)
  2. Verify the remote filesystem layout so the command resolves a real absolute path
  3. 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

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


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)