Hmbown/CodeWhale · error

Failed to run git diff. Is git installed?

Error message

Failed to run git diff. Is git installed? ({e})

What it means

Thrown when spawning the external `git diff` command fails at the OS level — the error message explicitly hints that git may not be installed. This wraps std::io::Error from `cmd.output()`, meaning the process could not be started at all (as opposed to git running but returning a non-zero exit, which produces the separate 'git diff failed: <stderr>' error).

Solutions

  1. Install git (`apt-get install git`, `brew install git`, `winget install Git.Git`)
  2. Check `git --version` in the same shell/PATH context the app runs in
  3. Fix PATH for the service/container so it includes the directory containing git
  4. If git exists but lacks +x, chmod +x the binary or reinstall

Example fix

// before
let output = cmd.output()
    .map_err(|e| anyhow::anyhow!("Failed to run git diff. Is git installed? ({e})"))?;
// after
// ensure git is present first
if which::which("git").is_err() { bail!("git is not installed or not on PATH"); }
let output = cmd.output()
    .map_err(|e| anyhow::anyhow!("Failed to run git diff. Is git installed? ({e})"))?;
Defensive patterns

Strategy: fallback

Validate before calling

// Rust
let git_ok = std::process::Command::new("git").arg("--version").output()
    .map(|o| o.status.success()).unwrap_or(false);
if !git_ok { eprintln!("git is not installed or not on PATH"); }

Try / catch

// Rust
match get_diff(args) {
    Ok(diff) => diff,
    Err(e) if e.to_string().contains("Is git installed") => {
        eprintln!("git missing: {e:#}");
        std::process::exit(2);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: `cmd.output()` errors when running `git diff` (with optional `-- <path>` args) — git binary missing from PATH, no exec permission, or the executable path is invalid.

Common situations: Fresh Docker/CI containers without git installed; minimal Windows or macOS environments lacking developer tools; a PATH that excludes /usr/bin in the sandbox or service context; a corrupted git installation.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/3c49a4231cababaa. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/lib.rs:9855

        )?
    } else {
        let mut cmd = crate::dependencies::Git::review_command(workspace)?;
        // Review repository content without executing its diff drivers.
        cmd.current_dir(workspace)
            .args(["diff", "--no-ext-diff", "--no-textconv"]);
        if args.staged {
            cmd.arg("--cached");
        }
        if let Some(base) = &args.base {
            cmd.arg(format!("{base}...HEAD"));
        }
        if let Some(path) = &args.path {
            cmd.arg("--").arg(path);
        }

        let output = cmd
            .output()
            .map_err(|e| anyhow::anyhow!("Failed to run git diff. Is git installed? ({e})"))?;
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            bail!("git diff failed: {}", stderr.trim());
        }
        String::from_utf8_lossy(&output.stdout).to_string()
    };
    if args.pr.is_none() {
        ensure_local_review_diff_fits(&diff, args.max_chars)?;
    }
    Ok(diff)
}

fn ensure_local_review_diff_fits(diff: &str, max_chars: usize) -> Result<()> {
    let chars = diff.chars().count();
    if chars > max_chars {
        bail!(
            "Complete local diff requires {chars} characters, exceeding the review limit of {max_chars}. No review was run and no receipt was written or accepted. Select an explicit --path scope, or increase --max-chars only if the selected model can accept the complete input."
        );

View on GitHub (pinned to 73e0f67d83)