Hmbown/CodeWhale · error

PR review plan did not partition the complete diff…

Error message

PR review plan did not partition the complete diff byte-for-byte

What it means

plan_pr_review reassembles all planned pieces and requires the concatenation to equal the original diff exactly (byte-for-byte). This is an internal invariant: the plan must partition the entire diff without dropping or altering any bytes. Failure means a piece was skipped, reordered, or mutated.

Solutions

  1. Update to a version with the splitting fix if you patched the planner locally
  2. Fix the splitter to cut only at complete hunk boundaries and never drop bytes
  3. Verify diff encoding/newlines are preserved through the piece pipeline
  4. Run the pr_batch_plan_* tests to reproduce which files lose bytes

Example fix

// before
let cut = hunk_start + max_chars; // arbitrary byte cut
// after
let cut = last_complete_hunk_end_within(max_chars); // boundary-preserving cut
Defensive patterns

Strategy: validation

Validate before calling

debug_assert_eq!(pieces.iter().map(|p| p.text.len()).sum::<usize>(), diff.len());

Try / catch

match plan_pr_review(...) { Err(e) if e.to_string().contains("byte-for-byte") => { log pieces; return Err(e); } ... }

Prevention

When it happens

Trigger: A code change to the hunk-splitting or grouping logic drops or rewrites bytes; oversized-file splitting cuts at a non-boundary; pieces for skipped files are omitted but the rebuild check still runs.

Common situations: Regressions after modifying PrReviewPiece building or splitting logic; diffs with CRLF or unusual encodings mishandled by the rebuild path; hunk-boundary arithmetic off by one.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/tools/review.rs:532

                rebuilt.push_str(&piece.diff[piece.header_bytes..]);
                pieces.push(piece);
            }
            PrReviewAtom::Skipped {
                patch,
                label,
                chars,
                reason,
            } => {
                rebuilt.push_str(patch);
                skipped.push(PrReviewSkippedFile {
                    file: label,
                    reason: reason.to_string(),
                    chars,
                });
            }
        }
    }
    anyhow::ensure!(
        rebuilt == diff,
        "PR review plan did not partition the complete diff byte-for-byte"
    );

    let mut grouped: Vec<Vec<PrReviewPiece<'_>>> = Vec::new();
    let mut current: Vec<PrReviewPiece<'_>> = Vec::new();
    let mut current_chars = 0;
    for piece in pieces {
        let piece_chars = super::review_pr::model_diff(&piece.diff).chars().count();
        if !current.is_empty() && current_chars + piece_chars > max_chars {
            grouped.push(std::mem::take(&mut current));
            current_chars = 0;
        }
        current.push(piece);
        current_chars += piece_chars;
    }
    if !current.is_empty() {
        grouped.push(current);

View on GitHub (pinned to 73e0f67d83)