jdx/mise · error

{kind} returned an unsafe absolute path: {path:?}

Error message

{kind} returned an unsafe absolute path: {path:?}

What it means

mise runs remote probes whose stdout must be a single absolute path — 'remote login executable' is the output of 'command -v <name>' when remote_mise is a bare name, and 'remote login home' is the remote $HOME used to expand '~/...' remote_mise paths. validated_absolute_remote_path_output rejects output that does not start with '/' or contains NUL/newline/CR before it is used to build commands.

Source

Thrown at src/system/remote.rs:1659

    }
    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_remote_executable(command: &str) -> Result<()> {
    validate_value("mise command", command)?;
    let is_path = command.contains('/');
    if command.starts_with('-')
        || command.contains(['\n', '\r'])
        || (!is_path && command.chars().any(char::is_whitespace))
    {
        bail!("remote mise command must be an executable name or path: {command:?}");
    }
    Ok(())
}

fn shell_quote(value: &str) -> String {
    shell_words::join([value])

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Check the {kind} placeholder: 'remote login executable' means command -v failed; 'remote login home' means $HOME resolution failed
  2. For the executable case run ssh <dest> sh -lc 'command -v mise' — if empty, install mise on the remote or reference it by absolute path: remote_mise = "/usr/local/bin/mise"
  3. For the home case verify ssh <dest> sh -lc 'printf %s\\n "$HOME"' prints one absolute path; fix HOME in the remote login environment if not
  4. Silence any login-shell banner output that appends extra lines to these probes

Example fix

# before: [remote.prod] host = "build.example.com" remote_mise = "mise" # not on remote login PATH
# after:
[remote.prod]
host = "build.example.com"
remote_mise = "~/.local/bin/mise" # expanded against the remote $HOME, or use an absolute path
Defensive patterns

Strategy: validation

Validate before calling

ssh "$dest" sh -lc 'command -v mise' | head -1 | grep -q '^/' && echo ok || echo "remote login executable not absolute"
ssh "$dest" sh -lc 'printf "%s\n" "$HOME"' | head -1 | grep -q '^/' && echo ok || echo "remote HOME not absolute"

Prevention

When it happens

Trigger: resolve_login_path_executable() with remote_mise = "mise": the script exits 127 with empty stdout when mise is not on the remote login PATH, yielding '' which fails the '/' check; resolve_configured_remote_mise() with remote_mise = "~/bin/mise" when $HOME is unset/relative or the printf output carries a CR or extra lines from profile noise.

Common situations: remote_mise set to a bare name on a host where mise was installed via a non-login method (not in .profile PATH), remotes where HOME is not set for the ssh forced-command environment, banner-printing login shells appending lines, and CRLF-emitting shells.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/180d90e08738c53d. Report an issue: GitHub.