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
- Read the stderr appended to the message to identify the child failure and fix the underlying cause
- Run the same command manually with the same args/env to reproduce the child's error
- Ensure the required tool/dependency is installed and on PATH in the environment mise uses
- 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
- Validate that the external binary exists on PATH before spawning
- Run commands non-interactively and with explicit env/cwd
- Keep tool dependencies pinned in [tools] so child tools are present
- Log full command lines with MISE_DEBUG=1 when debugging
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
- bootstrap from repository failed with {status}
- exited with non-zero status: {status}
- {display_program} {display_args} failed: exit code {} {}
- command exited with non-zero status: {status}
- command ["rustup", "check"] exited with code {}. stderr: {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/bbd19aca630b8b2b.
Report an issue: GitHub.