{"record":{"id":"b5f82cb4b26cb516","repo":"rtk-ai/rtk","slug":"stat-p-must-parse","errorCode":null,"errorMessage":"--stat -p must parse","messagePattern":"--stat -p must parse","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmds/git/diff_cmd.rs","lineNumber":6380,"sourceCode":"        let fixture = include_str!(\"../../../tests/fixtures/diff/git_diff_latin1_raw.txt\");\n        let out = condense_unified_diff_strict(fixture).expect(\"must parse\");\n        assert!(\n            out.contains(\"[file] \\\"caf\\\\350.txt\\\" (+1 -1)\"),\n            \"got:\\n{out}\"\n        );\n        assert!(\n            out.contains(\"[file] \\\"caf\\\\351.txt\\\" (+1 -1)\"),\n            \"got:\\n{out}\"\n        );\n        assert!(!out.contains('\\u{FFFD}'), \"got:\\n{out}\");\n    }\n\n    #[test]\n    fn git_stat_separator_and_format_b_prose_condense() {\n        // Real `git log --stat -p`: a bare `---` between the message and\n        // the diffstat used to read as lost content.\n        let stat = include_str!(\"../../../tests/fixtures/diff/git_log_p_stat_raw.txt\");\n        let out = condense_unified_diff_strict(stat).expect(\"--stat -p must parse\");\n        assert!(out.contains(\"[file] i.py (+1 -1)\"), \"got:\\n{out}\");\n        assert!(out.contains(\"[file] m.txt (mode changed)\"), \"got:\\n{out}\");\n        // Real `git show --format=%B`: body prose starting with `diff `\n        // used to arm the GNU latch and send the stream raw.\n        let b = include_str!(\"../../../tests/fixtures/diff/git_show_format_B_raw.txt\");\n        let out = condense_unified_diff_strict(b).expect(\"--format=%B must parse\");\n        assert_eq!(out, \"[file] w.txt (+1 -0)\\n+zz\");\n    }\n\n    #[test]\n    fn combined_diffs_with_three_parents_parse() {\n        // Real octopus merge: `@@@@` with three old ranges, via `git show\n        // --cc` and via `git diff-tree -c` (`diff --combined`).\n        for fixture in [\n            include_str!(\"../../../tests/fixtures/diff/git_show_cc_octopus_raw.txt\"),\n            include_str!(\"../../../tests/fixtures/diff/git_diff_tree_combined_raw.txt\"),\n        ] {\n            let out = condense_unified_diff_strict(fixture).expect(\"must parse\");","sourceCodeStart":6362,"sourceCodeEnd":6398,"githubUrl":"https://github.com/rtk-ai/rtk/blob/0924356b4caba4989607227b7c8824d3d8098719/src/cmds/git/diff_cmd.rs#L6362-L6398","documentation":"In test `git_stat_separator_and_format_b_prose_condense` (src/cmds/git/diff_cmd.rs:6376), `.expect(\"--stat -p must parse\")` panics because `condense_unified_diff_strict` returned `None` for the fixture `tests/fixtures/diff/git_log_p_stat_raw.txt` (real `git log --stat -p` output). The stream contains a bare `---` separator between the commit message and the diffstat; the parser must treat it as a separator (not lost content) and produce `[file] i.py (+1 -1)` plus `[file] m.txt (mode changed)`.","triggerScenarios":"Running `cargo test git_stat_separator_and_format_b_prose_condense`: parsing `git log --stat -p` capture with the bare `---` separator, or the paired `git show --format=%B` capture whose body prose begins with `diff `. Either shape returning `None` triggers the panic at line 6380 (or the analogous `--format=%B` expect a few lines below).","commonSituations":"Edits to how the parser handles diffstat sections (`file | N +-` lines) or the bare `---` divider; changes to the GNU 'latch' arming logic that made prose starting with `diff ` re-arm or disarm incorrectly and reject the stream; new guards for commit-message regions that are too strict and bail on the whole input.","solutions":["Run `cargo test git_stat_separator_and_format_b_prose_condense -- --nocapture` to see whether the `--stat -p` or `--format=%B` block panics.","Check the diffstat/`---`-separator handling in `condense_unified_diff_strict` (src/cmds/git/diff_cmd.rs:2083): a bare `---` before diffstat lines must not mark content as lost or abort parsing.","Verify the GNU latch logic treats commit-body prose starting with `diff ` as prose (does not re-arm the raw passthrough).","Add minimal inline inputs (message + `---` + diffstat; body prose `diff ...` + real hunk) so both shapes stay covered."],"exampleFix":"// before\nlet out = condense_unified_diff_strict(stat).expect(\"--stat -p must parse\");\n// after\nlet out = condense_unified_diff_strict(stat)\n    .unwrap_or_else(|| panic!(\"--stat -p fixture fell back raw:\\n{stat}\"));","handlingStrategy":"validation","validationCode":"let stat = include_str!(\"tests/fixtures/diff/git_log_p_stat_raw.txt\");\nassert!(condense_unified_diff_strict(stat).is_some(), \"--stat -p stream must parse\");","typeGuard":"fn condenses(diff: &str) -> bool { condense_unified_diff_strict(diff).is_some() }","tryCatchPattern":"let out = condense_unified_diff_strict(stat)\n    .unwrap_or_else(|| panic!(\"--stat -p fixture fell back raw:\\n{stat}\"));","preventionTips":["Treat a bare `---` between commit message and diffstat as a separator, never as lost content","Test both --stat -p and --format=%B captures whenever latch/message-region logic changes","Prose starting with `diff ` must not re-arm raw passthrough; keep a dedicated test for it","Run the full diff_cmd test module after edits to diffstat or separator handling"],"tags":["rust","test","parser","git-log","diffstat"],"backgroundTag":"internal-invariant-violation","analyzedSha":"0924356b4caba4989607227b7c8824d3d8098719","analyzedAt":"2026-09-19T19:25:29.612Z","contentChangedAt":"2026-09-19T19:25:29.612Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}