jdx/mise · error

bootstrap_command returned an unsafe mise path

Error message

bootstrap_command returned an unsafe mise path: {command:?}

What it means

mise runs a bootstrap command on a remote host to locate where mise was installed. Before using the returned string, `validated_remote_command` requires it to be an absolute path containing no NUL, newline, or carriage-return bytes; otherwise this error is thrown to prevent injecting arbitrary shell content or relative/truncated paths into remote shell commands.

Solutions

  1. Fix the remote bootstrap_command so it prints exactly one absolute path and nothing else (e.g. suppress rc-file output, use `command -v mise` with stderr redirected)
  2. Ensure mise is installed on the remote at a real absolute path (not an alias or shell function)
  3. Check for a broken remote helper/ssh wrapper emitting CR/LF or NUL bytes and fix its output encoding

Example fix

// before
bootstrap_command = "mise which mise"  // prints relative or extra lines
// after
bootstrap_command = "command -v mise 2>/dev/null"  // single absolute path, stderr silenced
Defensive patterns

Strategy: validation

Validate before calling

function isSafeRemotePath(s) {
  return typeof s === 'string' && s.startsWith('/') && !/[\0\n\r]/.test(s);
}
if (!isSafeRemotePath(output)) throw new Error('bootstrap output is not a safe absolute path');

Type guard

const isSafeRemotePath = (s: unknown): s is string =>
  typeof s === 'string' && s.startsWith('/') && !/[\0\n\r]/.test(s);

Try / catch

try {
  let path = validated_remote_command(output);
} catch (e) {
  if (String(e).includes('unsafe mise path')) {
    // inspect raw remote output, fix bootstrap_command, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: The remote `bootstrap_command` (e.g. `which mise`, `command -v mise`, or a custom script) prints a relative path, a multiline/annotated string (shell init output, MOTD text, aliases), or a path containing NUL/CR/LF.

Common situations: Custom bootstrap_command in remote.toml that echoes extra lines; remote shell rc-files printing banners before `which`; mise installed via an alias rather than a real path; NUL-corrupted output from a broken remote helper.

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/befd664e7e1095aa. Report an issue: GitHub.

Appendix: source

Thrown at src/system/remote.rs:2196

    if value.is_empty() || value.contains('\0') {
        bail!("remote {kind} cannot be empty or contain NUL");
    }
    Ok(())
}

fn validate_staging_path(path: &str) -> Result<()> {
    if !path.starts_with("/tmp/mise-bootstrap.")
        || path["/tmp/mise-bootstrap.".len()..].is_empty()
        || path.chars().any(char::is_whitespace)
    {
        bail!("remote mktemp returned an unsafe staging path: {path:?}");
    }
    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)?;

View on GitHub (pinned to 533346cc37)