jdx/mise · error

remote mise command must be an executable name or path: {com

Error message

remote mise command must be an executable name or path: {command:?}

What it means

remote_mise must be a single executable token: validate_remote_executable rejects values that start with '-', contain newlines/CRs, or — when they contain no '/' — contain any whitespace. The intent is one argv element: either a bare command name like 'mise' or a path like '/usr/local/bin/mise'; arguments are not allowed in this field.

Source

Thrown at src/system/remote.rs:1508

    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])
}

fn normalize_os(value: &str) -> String {
    match value.trim().to_ascii_lowercase().as_str() {
        "darwin" | "macos" => "macos".to_string(),
        "linux" => "linux".to_string(),
        other => other.to_string(),
    }
}

fn normalize_arch(value: &str) -> String {
    match value.trim().to_ascii_lowercase().as_str() {

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Use a single token: remote_mise = "mise" or remote_mise = "/usr/local/bin/mise"
  2. Put mise arguments in the actual task/command invocation, not in remote_mise
  3. Trim whitespace/newlines from generated or environment-supplied values
  4. If a wrapper is needed, create a remote shell script with an absolute path and point remote_mise at it

Example fix

# before (mise.toml)
remote_mise = "mise run --cd /srv"

# after
remote_mise = "/usr/local/bin/mise"
Defensive patterns

Strategy: validation

Validate before calling

# lint remote_mise values: one token, no leading dash, args not allowed
case "$REMOTE_MISE" in
  -*|*" "*|*"$'\n'"*) echo "invalid remote_mise: $REMOTE_MISE";;
  *) echo ok;;
esac

Type guard

fn remoteMiseValid(cmd: &str) -> bool {
    let is_path = cmd.contains('/');
    !cmd.is_empty()
        && !cmd.contains('\0')
        && !cmd.starts_with('-')
        && !cmd.contains(['\n', '\r'])
        && (is_path || !cmd.chars().any(char::is_whitespace))
}

Try / catch

if !remoteMiseValid(&configured) {
    return Err(eyre::eyre!("remote_mise must be a single executable name or path"));
}
host.validate()?;

Prevention

When it happens

Trigger: Setting remote_mise = "mise run" or "/opt/mise/mise --verbose" (space + no slash, or treated as one atom); a value beginning with '-' would be parsed as an ssh flag; embedded newlines break the one-line contract.

Common situations: Users trying to pass flags through remote_mise; copy-pasting a full command line from docs; trailing whitespace/newline accidentally included when the value comes from an env var or generated config.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/48662249ccecb87d. Report an issue: GitHub.