jdx/mise · error

exited with non-zero status

Error message

exited with non-zero status: {status}

What it means

The command spawned by execute_hashes_async_with_drain_timeout finished with a non-zero exit status and no timeout fired, so mise reports the raw status. This is the plain "command failed" case: the tool ran to completion (or was killed for another reason) and returned failure. Because output is hashed rather than captured here, the message carries only the status, not the program's stderr.

Solutions

  1. Re-run the command manually to see its actual stdout/stderr (this API only returns hashes)
  2. Fix the underlying tool error indicated when run manually
  3. Check that the program and its arguments are correct and any sub-commands exist on PATH
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the program exists before invoking
which git || echo 'git missing from PATH'

Try / catch

match cmd.execute_hashes_async(MAX).await {
    Ok(h) => Ok(h),
    Err(e) if e.to_string().starts_with("exited with non-zero status") => {
        eprintln!("command failed: {e}; rerun manually to see its output");
        Err(e)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Any command run through execute_hashes_async that exits non-zero — a failing build, a script erroring, a tool writing diagnostics to stderr and exiting 1/2/127.

Common situations: Compilation errors, missing arguments to the underlying tool, exit code 127 for a command that itself failed to find a sub-executable, or a script with `set -e` bailing early.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


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

Appendix: source

Thrown at src/cmd.rs:1472

            };
            if let Err(err) = consume(output) {
                #[cfg(unix)]
                signal_process_tree(id, nix::sys::signal::Signal::SIGKILL);
                #[cfg(windows)]
                kill_process_tree(id);
                return Err(err);
            }
        }

        if let Some(guard) = &timeout_guard {
            guard.cancel();
        }
        let status = status.expect("command wait must complete");
        if !status.success() {
            if let Some(timeout) = timeout_guard.as_ref().and_then(|guard| guard.timed_out()) {
                bail!("timed out after {timeout:?}");
            }
            bail!("exited with non-zero status: {status}");
        }
        Ok((
            stdout_hasher.finalize().to_hex().to_string(),
            stderr_hasher.finalize().to_hex().to_string(),
        ))
    }

    /// Run the command and return stdout, even when raw mode is enabled.
    pub(crate) async fn read(mut self) -> Result<String> {
        let _read_lock = raw_read_lock().await;
        debug!("$ {self}");
        self.cmd.kill_on_drop(true);
        #[cfg(unix)]
        if should_use_pgroup() {
            self.cmd.env(TASK_PGID_MANAGED_ENV, "1");
            unsafe {
                self.cmd.as_std_mut().pre_exec(|| {
                    let stdin = std::os::fd::BorrowedFd::borrow_raw(0);

View on GitHub (pinned to 533346cc37)