rtk-ai/rtk · warning

version notes must stay prose

Error message

version notes must stay prose

What it means

Test panic from `.expect("version notes must stay prose")`: `condense_unified_diff_strict` failed (or its output lost the file entry / leaked prose) on a format-patch whose commit message contains kernel-style version notes (`Changes in v2:` plus `- ` bullets) placed between the `---` separator and the diffstat. The contract is that these column-0 bullets remain prose and do not reset the bullet tolerance, so parsing must still succeed and `rebased` must be dropped with the rest of the prose.

Solutions

  1. Inspect the parser error by unwrapping with the message included, then check where tolerance for column-0 bullets ends (should be at the diffstat, not at `---`).
  2. Ensure prose detected between `---` and the diffstat is dropped from output rather than re-emitted or forcing a raw fallback.
  3. Add the failing series shape as a fixture so the b4 convention stays covered.

Example fix

// before
let out = condense_unified_diff_strict(&notes).expect("version notes must stay prose");
// after
let out = condense_unified_diff_strict(&notes)
    .unwrap_or_else(|e| panic!("version notes must stay prose: {e}"));
Defensive patterns

Strategy: validation

Validate before calling

// guard: version-note bullets must appear before the diffstat line
assert!(notes.contains("---\nChanges in v2:") && notes.contains(" y.txt | 2 +-"));

Try / catch

let out = condense_unified_diff_strict(&notes)
    .unwrap_or_else(|e| panic!("version notes must stay prose: {e}"));

Prevention

When it happens

Trigger: Passing a patch series where `---` is followed by `Changes in v2:` / `- rebased` / `- dropped the hack` before the ` y.txt | 2 +-` diffstat — any code path that counts those bullets as marked lines past the separator breaks the parse or leaks the text.

Common situations: Real git format-patch output from kernel/b4 workflows routinely carries version-change notes in exactly this position; changes to the strict parser's bullet-tolerance window break these inputs.

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 rtk-ai/rtk@0924356b4c (2026-09-19). Data as JSON: /api/errors/7348e9c44e725709. Report an issue: GitHub.

Appendix: source

Thrown at src/cmds/git/diff_cmd.rs:6905

        );
        // The intact series (with the block restored) still parses, bullets
        // and separators included, and the signature is not counted.
        let intact = series.replace(
            "\n-p\n+q\n",
            "\ndiff --git a/y.txt b/y.txt\n--- a/y.txt\n+++ b/y.txt\n@@ -1 +1 @@\n-p\n+q\n",
        );
        let out = condense_unified_diff_strict(&intact).expect("intact series must parse");
        assert!(out.contains("[file] y.txt (+1 -1)"), "got:\n{out}");
        assert!(!out.contains("bullet"), "got:\n{out}");
        // Version notes between `---` and the diffstat (the kernel / b4
        // convention) are column-0 bullets past the separator; they must
        // stay prose, which is why the tolerance ends at the diffstat and
        // not at `---`.
        let notes = intact.replace(
            "---\n y.txt | 2 +-",
            "---\nChanges in v2:\n- rebased\n- dropped the hack\n\n y.txt | 2 +-",
        );
        let out = condense_unified_diff_strict(&notes).expect("version notes must stay prose");
        assert!(out.contains("[file] y.txt (+1 -1)"), "got:\n{out}");
        assert!(!out.contains("rebased"), "got:\n{out}");
    }

    #[test]
    fn a_prose_table_is_not_a_diffstat() {
        // A markdown table in the commit message is space-indented and holds
        // a ` | `, but it is prose: the bullet after it must stay prose too,
        // not read as a marked line past the diffstat.
        let base = "From fe6a6d0d8316535b5ac232f5d7cc6d227b187b9e Mon Sep 17 00:00:00 2001\nSubject: [PATCH] one\n\n col | val\n --- | ---\n row | text\n- a bullet after the table\n---\nSTAT\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/x.txt b/x.txt\n--- a/x.txt\n+++ b/x.txt\n@@ -1 +1 @@\n-a\n+b\n-- \n2.54.0\n";
        let out = condense_unified_diff_strict(&base.replace("STAT", " x.txt | 2 +-"))
            .expect("a table in the message must not force raw");
        assert!(out.contains("[file] x.txt (+1 -1)"), "got:\n{out}");
        assert!(!out.contains("bullet"), "got:\n{out}");

        // Every diffstat shape format-patch emits still ends the tolerance,
        // so a marked line after one is still lost content. The bare count
        // covers a pure rename or mode change, which stats as `0`.

View on GitHub (pinned to 0924356b4c)