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

  1. Confirm you are in a repo: `git rev-parse --show-toplevel`
  2. Verify the base ref resolves: `git rev-parse <base>`; fix master/main typos
  3. Remove a stale .git/index.lock only after confirming no git process is running
  4. Re-run with a corrected --path or without it
  5. 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

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


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/1e92d94fc154cef3. Report an issue: GitHub.