Hmbown/CodeWhale · error · anyhow::Error
git diff failed: {}
Error message
git diff failed: {} What it means
The review diff runner spawns `git diff` (optionally `base...HEAD`, `--staged`, path filters) and bails with git's stderr on non-zero exit. It means git refused to compute the diff -- repo, ref, or path problems -- not that the diff was empty.
Source
Thrown at crates/tui/src/lib.rs:8382
let mut cmd = crate::dependencies::Git::command()
.ok_or_else(|| anyhow::anyhow!("git not found on PATH"))?;
cmd.arg("diff");
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());
}
let mut diff = String::from_utf8_lossy(&output.stdout).to_string();
if diff.len() > args.max_chars {
diff = crate::utils::truncate_with_ellipsis(&diff, args.max_chars, "\n...[truncated]\n");
}
Ok(diff)
}
fn review_target_label(args: &ReviewArgs) -> String {
let mut label = if args.staged {
"staged".to_string()
} else if let Some(base) = args
.base
.as_deref()
.map(str::trim)
.filter(|base| !base.is_empty())
{
format!("base:{base}")View on GitHub (pinned to 0c42157ee5)
Solutions
- Confirm you are in a repo: `git rev-parse --show-toplevel`
- Verify the base ref resolves: `git rev-parse <base>`; fix master/main typos
- Remove a stale .git/index.lock only after confirming no git process is running
- Re-run with a corrected --path or without it
- Reproduce manually with the same git diff arguments to see the raw stderr
Example fix
# before codewhale review --base main # git diff failed: fatal: ambiguous argument 'main...HEAD' # after git branch --show-current # base is actually 'master' codewhale review --base master
Defensive patterns
Strategy: validation
Validate before calling
test "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = true || { echo 'not a git repo'; exit 1; }
git rev-parse --verify -q "$BASE^{commit}" >/dev/null || { echo "base ref '$BASE' does not resolve"; exit 1; } Try / catch
match run_review(config, args).await {
Err(e) if e.to_string().contains("git diff failed") => { eprintln!("git-level problem: {e:#}"); fix_base_ref(); }
other => other?,
} Prevention
- Verify repo and base refs before invoking review (`git rev-parse <base>`)
- Avoid running review while another git process may hold .git/index.lock
- Derive --base from `git branch --show-current` or remote HEAD instead of hardcoding
When it happens
Trigger: Running review outside a git work tree; `--base` naming an unknown ref so `base...HEAD` is ambiguous; a path argument git rejects; a stale `.git/index.lock` held by another git process.
Common situations: Base-branch typo after clone defaults changed (main vs master); IDE running a git operation concurrently holding index.lock; invoking from a non-repo subdirectory; renamed/deleted path passed via --path.
Related errors
- git worktree add failed for branch {} at {}{}{}
- No diff to review.
- worktree branch must not be empty
- repo root does not exist: {}
- dsh exited with status {code}
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/1e92d94fc154cef3.
Report an issue: GitHub.