Hmbown/CodeWhale · error

Incomplete PR diff: a text hunk is truncated or malformed

Error message

Incomplete PR diff: a text hunk is truncated or malformed

What it means

complete_file_set walks the fetched `git diff` line by line, tracking how many hunk lines remain per file. When a hunk ends with fewer remaining context/addition/deletion lines than the header promised — or contains a line the state machine does not recognize — the diff is truncated or malformed and the review is rejected rather than performed on partial content.

Solutions

  1. Re-fetch the diff (`gh pr diff`/`git diff` path in fetch_diff) and confirm the byte count matches the PR's additions+deletions plus headers
  2. Remove any pager/filter wrappers between git and the tool (`GIT_PAGER=cat`, `core.pager=cat`, no external diff drivers)
  3. Verify no output truncation happened (check the 64KiB bounded readers in run_command and any size limits); re-run the review on the complete diff

Example fix

// before: piping diff through a pager/mangler
git diff base...head | less
// after: plain, no-ext-diff, no pager
git diff --no-ext-diff --no-color base...head
Defensive patterns

Strategy: validation

Validate before calling

// verify hunk line counts before review
for hunk in diff.lines().filter(|l| l.starts_with("@@")) {
    let (_, old, new) = parse_hunk_header(hunk).ok_or("bad header")?;
    // count following +/ -/space lines and compare to old/new
}

Try / catch

match diff_with(&view) {
    Err(e) if e.to_string().contains("truncated or malformed") => eprintln!("diff incomplete; refetch with GIT_PAGER=cat git diff --no-ext-diff"),
    other => other?,
}

Prevention

When it happens

Trigger: The diff text emitted by `git diff` was cut off (output limit, killed process, corrupted pipe) or a hunk body has fewer lines than the @@ -a,b +c,d @@ header counts, leaving the line matcher at a non-continuation token.

Common situations: Hitting the bounded stdout read cap on very large diffs; a pager or filter mangling output (missing --no-ext-diff equivalent); tools post-processing the diff text and dropping lines; copying diffs through processes that trim trailing context.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/tools/review_pr.rs:191

    let mut has_patch = false;
    let mut has_full_index = false;
    for line in diff.lines() {
        if remaining != (0, 0) {
            match line.as_bytes().first() {
                Some(b'+') if remaining.1 > 0 => {
                    remaining.1 -= 1;
                    additions += 1;
                }
                Some(b'-') if remaining.0 > 0 => {
                    remaining.0 -= 1;
                    deletions += 1;
                }
                Some(b' ') if remaining.0 > 0 && remaining.1 > 0 => {
                    remaining.0 -= 1;
                    remaining.1 -= 1;
                }
                Some(b'\\') => {}
                _ => bail!("Incomplete PR diff: a text hunk is truncated or malformed"),
            }
            continue;
        }
        if line.starts_with("diff --git ") {
            if files > 0 && !has_patch {
                bail!("Incomplete PR diff: a file patch is missing");
            }
            files += 1;
            has_patch = false;
            has_full_index = false;
        } else if line.starts_with("index ") {
            has_full_index = full_index_objects(line);
        } else if let Some((_, old, new)) = super::review_hunks::parse_hunk_header(line) {
            remaining = (old, new);
            has_patch = true;
        } else if line.starts_with("@@") {
            bail!("Incomplete PR diff: malformed hunk header");
        } else if [

View on GitHub (pinned to 73e0f67d83)