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

  1. Run the same command manually to capture its real stderr/stdout
  2. Fix the failing child command's environment (PATH, files, permissions)
  3. Check mise debug logs for the exact command line executed
  4. 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

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


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