jdx/mise · error

{display_program} {display_args} failed: exit code {} {}

Error message

{display_program} {display_args} failed: exit code {}
{}

What it means

A helper command executed by cmd_read_async failed with a non-zero exit code; mise wraps the program, its arguments, the exit code, and the command's trimmed stderr into one error. This is the generic 'external command failed' path for async command reads used across backends.

Source

Thrown at src/cmd.rs:2034

    let display_program = program.to_string_lossy();
    let display_args = args.join(" ");
    debug!("$ {display_program} {display_args}");

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

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        bail!(
            "{display_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!("{display_program} produced invalid UTF-8 output"))?;
    Ok(stdout.trim_end().to_string())
}

/// Like [`cmd_read_async`] but **inherits** the current process environment,
/// only adding the provided extra variables on top.
///
/// Use this for core plugins that need the ambient PATH / locale / etc.
pub(crate) async fn cmd_read_async_inherited_env<I, K, V>(
    program: &str,
    args: &[&str],

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Read the stderr embedded in the error message — it contains the child's actual failure reason.
  2. Verify the failing program is installed and on PATH inside mise's environment (`mise x -- which <prog>`).
  3. Fix the underlying cause (credentials, network, bad args, missing repo/file).
  4. If the command legitimately fails sometimes, handle the error at the call site instead of propagating it.

Example fix

// before: opaque failure because git runs outside the repo
let out = cmd_read_async("git", ["rev-parse", "HEAD"]).await?;

// after: run with the correct working directory / check preconditions
let out = cmd("git").args(["rev-parse", "HEAD"]).current_dir(project_root).read_async().await?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the helper program exists and works before invoking it:
command -v git >/dev/null 2>&1 || { echo "git not on PATH" >&2; exit 127; }
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { echo "not a git repo" >&2; exit 1; }

Try / catch

match cmd_read_async(program, args).await {
    Err(e) => {
        // error text already embeds exit code + stderr from the child
        eprintln!("helper failed: {e}");
        // inspect e chain / stderr for the root cause before retrying
    }
    Ok(out) => out,
}

Prevention

When it happens

Trigger: Raised at src/cmd.rs:2034 in cmd_read_async when `output.status.success()` is false after `Command::output().await`; the error text embeds `exit code N` (or -1 if killed by a signal) plus the child's stderr.

Common situations: Backend helper invocations failing — e.g. `git` not finding a repo, a version-listing tool not installed or on PATH, curl/gh failing with auth or network errors, or scripts exiting non-zero due to bad configuration.

Related errors


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