jdx/mise · error
command exited with non-zero status: {status}
Error message
command exited with non-zero status: {status} What it means
Raised by read_isolated in src/cmd/bounded.rs after a bounded command completes but reports a non-success exit status. Unlike error 420 this is the bounded-reader variant: it returns the raw `ExitStatus` display rather than stderr content. It signals the isolated child command failed.
Source
Thrown at src/cmd/bounded.rs:53
child.wait(),
capture(stdout, &budget, limit),
capture(stderr, &budget, limit)
)
})
.await;
let (status, stdout, _stderr) = match result {
Ok(Ok(output)) => output,
Ok(Err(err)) => {
end(&mut child, tree).await;
return Err(err.into());
}
Err(_) => {
end(&mut child, tree).await;
bail!("timed out after {timeout:?}");
}
};
if !status.success() {
bail!("command exited with non-zero status: {status}");
}
Ok(String::from_utf8(stdout)?.trim_end().to_string())
}
}
/// How long reaping a killed command may take before it is left to the
/// operating system. A process that has been killed is normally gone at
/// once; one that is not is no reason to outlive the deadline.
const REAP: Duration = Duration::from_secs(1);
/// End the command and account for it, without waiting on a process that
/// may not be listening. Closing the tree kills the group, but the direct
/// child can be outside it — on Windows it may never have joined the job,
/// and on unix it can have left the group — and `kill_on_drop` cannot run
/// while this is the task awaiting the child. So kill it here, and bound
/// the wait: a deadline anything can extend is not a deadline.
async fn end(child: &mut tokio::process::Child, tree: ChildTree) {
drop(tree);View on GitHub (pinned to afd2eddd3a)
Solutions
- Run the same command manually to capture its real stderr/stdout
- Fix the failing child command's environment (PATH, files, permissions)
- Check mise debug logs for the exact command line executed
- Guard the call site if non-zero is an expected outcome for some inputs
Example fix
// before: failing script `mytool --list-versions` exits 1 due to missing config // after: create the expected config or use `mytool --list-versions --fallback`
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight the command outside the bounded reader
let status = Command::new(program).args(args).status()?;
if !status.success() {
eprintln!("{program} exits non-zero in this environment");
} Try / catch
match read_isolated(&mut cmd, timeout, &tree).await {
Ok(out) => out,
Err(e) if e.to_string().contains("non-zero status") => {
// re-run the command directly to capture stderr, then decide
diagnose_with_direct_run(program, args)
}
Err(e) => return Err(e),
} Prevention
- Test the exact command with the same args/env mise uses
- Check file permissions and cwd assumptions of the child script
- Pin the child tool version so behavior is stable
- Handle expected non-zero exits at the call site instead of letting them bubble
When it happens
Trigger: Calling read_isolated when the spawned command exits non-zero (after completing within the timeout).
Common situations: A version-listing or metadata command fails on an unexpected file layout; a script returns non-zero because of a missing file, bad permissions, or an incompatible environment.
Related errors
- bootstrap from repository failed with {status}
- exited with non-zero status: {status}
- {display_program} {display_args} failed: exit code {} {}
- {program} {display_args} failed: exit code {} {}
- command ["rustup", "check"] exited with code {}. stderr: {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/4ef12a1ddf677b8d.
Report an issue: GitHub.