gitbutlerapp/gitbutler · error · anyhow::Error

command exited with status {}

Error message

command exited with status {}

What it means

Thrown by the `but` TUI command mode after it spawns a user-requested shell command as a child process and that process exits with a non-zero status. The exit status is formatted (exit code and/or signal) and shown as a transient error in the TUI. It is the child command's own failure propagated into but, not a bug in but itself.

Source

Thrown at crates/but/src/command/legacy/status/tui/app/command_mode.rs:240

                    return Ok(());
                } else {
                    return Err(err).context("failed to start command");
                }
            }
        };
        let status = child.wait()?;

        if !IN_TEST {
            out.prompt_single_line("\npress enter to continue...")?;
        }

        if status.success() {
            messages.extend([
                Message::EnterNormalModeAfterConfirmingOperation,
                Message::Reload(None, ReloadCause::Mutation),
            ]);
        } else {
            self.push_transient_error(anyhow!(
                "command exited with status {}",
                format_exit_status(status)
            ));
        }

        drop(_suspend_guard);

        Ok(())
    }
}

/// Formats an exit status for human-readable error messages.
fn format_exit_status(status: std::process::ExitStatus) -> String {
    if let Some(code) = status.code() {
        code.to_string()
    } else {
        status.to_string()
    }

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Run the exact same command in a regular shell to see its real stdout/stderr and exit code
  2. Fix the command itself (binary name, arguments, required env vars) and rerun it from command mode
  3. Interpret the status: 127 = command not found, 126 = not executable, >= 128 = terminated by signal
  4. If the tool is not found, start but from a shell whose PATH includes it
Defensive patterns

Strategy: try-catch

Validate before calling

use which::which;

let (prog, _args) = split_cmd_word(&cmd_line);
if which(prog).is_err() {
    return Err(anyhow!("'{prog}' not found on PATH"));
}

Try / catch

Spawn with .output() instead of .wait() so the child's stderr is captured; match on the exit status and include stderr plus the numeric code in the transient error, mapping 127 to a dedicated 'command not found' hint.

Prevention

When it happens

Trigger: Entering command mode in the but TUI and running a command that fails: the binary is missing (shell exit 127), a git/build/test subcommand returns non-zero, or the process is killed by a signal.

Common situations: Running tests or git commands from the TUI on a failing tree; typos in the command; PATH differences between the interactive shell and the environment but was started in.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/ce577c449ac6ec76. Report an issue: GitHub.