jdx/mise · error

{program} {display_args} failed: exit code {} {}

Error message

{program} {display_args} failed: exit code {}
{}

What it means

This error is raised when an external command spawned by mise (via the async command runner in src/cmd.rs) exits with a non-zero status. It wraps the program name, its display arguments, the raw exit code, and the trimmed stderr output so the developer can see exactly what subprocess failed and why. It mirrors the child's failure rather than a mise-internal bug.

Source

Thrown at src/cmd.rs:2076

    V: AsRef<OsStr>,
{
    let display_args = args.join(" ");
    debug!("$ {program} {display_args}");

    let output = tokio::process::Command::new(program)
        .args(args)
        .envs(extra_env)
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .kill_on_drop(true)
        .output()
        .await
        .wrap_err_with(|| format!("failed to execute command: {program} {display_args}"))?;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        bail!(
            "{program} {display_args} failed: exit code {}\n{}",
            output.status.code().unwrap_or(-1),
            stderr.trim()
        );
    }

    let stdout = String::from_utf8(output.stdout)
        .wrap_err_with(|| format!("{program} produced invalid UTF-8 output"))?;
    Ok(stdout.trim_end().to_string())
}

#[cfg(test)]
#[cfg(unix)]
mod tests {
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::sync::{Arc, Mutex};

    use pretty_assertions::assert_eq;

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Read the stderr appended to the message to identify the child failure and fix the underlying cause
  2. Run the same command manually with the same args/env to reproduce the child's error
  3. Ensure the required tool/dependency is installed and on PATH in the environment mise uses
  4. Set MISE_DEBUG=1 to see the full command invocation that failed

Example fix

// before: vague failure, exit code 1 with empty context
// after: install the missing dependency indicated by stderr, e.g.
// mise install  ->  error: git clone ... failed: exit code 128
// fix: git config --global url."https://".insteadOf git:// or install git
Defensive patterns

Strategy: try-catch

Validate before calling

// before invoking, check the child tool exists
if !Path::new(program).exists() && which(program).is_none() {
    return Err(format!("{program} not found on PATH"));
}

Try / catch

match result {
    Ok(v) => v,
    Err(e) if e.to_string().contains("failed: exit code") => {
        // parse stderr from the message; surface a targeted fix or retry with corrected env
        eprintln!("external tool failed: {e}");
        fallback_path()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling any mise code path that shells out to an external program (e.g. a backend install step, git command, or plugin hook) when that program exits non-zero. The message includes exit code and stderr.

Common situations: A tool backend fails during install (network partial download, checksum script failing); a git command fails because the repo is dirty or the ref doesn't exist; a plugin's hook script errors; PATH/toolchain missing so the child fails at startup.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/bbd19aca630b8b2b. Report an issue: GitHub.