{"record":{"id":"ae301109b5a0876b","repo":"kovidgoyal/kitty","slug":"right-side-line-mismatch-d-d","errorCode":null,"errorMessage":"Right side line mismatch %d != %d","messagePattern":"Right side line mismatch (.+?) != (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kittens/diff/patch.go","lineNumber":329,"sourceCode":"\tself.removed_count++\n}\n\nfunc (self *Hunk) context_line() {\n\tself.ensure_context_chunk()\n\tself.current_chunk.context_line()\n}\n\nfunc (self *Hunk) finalize(left_lines, right_lines []string) error {\n\tif self.current_chunk != nil {\n\t\tself.chunks = append(self.chunks, self.current_chunk)\n\t}\n\t// Sanity check\n\tc := self.chunks[len(self.chunks)-1]\n\tif c.left_start+c.left_count != self.left_start+self.left_count {\n\t\treturn fmt.Errorf(\"Left side line mismatch %d != %d\", c.left_start+c.left_count, self.left_start+self.left_count)\n\t}\n\tif c.right_start+c.right_count != self.right_start+self.right_count {\n\t\treturn fmt.Errorf(\"Right side line mismatch %d != %d\", c.right_start+c.right_count, self.right_start+self.right_count)\n\t}\n\tfor _, c := range self.chunks {\n\t\tc.finalize(left_lines, right_lines)\n\t}\n\treturn nil\n}\n\ntype Patch struct {\n\tall_hunks                                       []*Hunk\n\tlargest_line_number, added_count, removed_count int\n\tleft_moved_lines, right_moved_lines             *utils.Set[int]\n}\n\nfunc (self *Patch) Len() int { return len(self.all_hunks) }\n\nfunc splitlines_like_git(raw string, strip_trailing_lines bool, process_line func(string)) {\n\tsz := len(raw)\n\tif strip_trailing_lines {","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/diff/patch.go#L311-L347","documentation":"The companion check to the left-side check in Patch.finalize: the last chunk's right_start+right_count must equal the patch's right_start+right_count. It verifies the right side of every hunk tiles the file contiguously; failure indicates malformed or mis-parsed diff output rather than a user input problem.","triggerScenarios":"Same as the left-side check: a custom diff_cmd emitting hunks whose right-side line counts don't sum correctly; diffs with headers claiming more/fewer lines than the hunk bodies contain; rename-only or binary hunks handled inconsistently by an external diff tool.","commonSituations":"Custom `diff_cmd` wrappers (delta, difftastic, custom scripts) in kitty.conf; diffs produced with unusual options (--unified=0 combined with word-diff, etc.); kitty version regressions in the patch parser.","solutions":["Revert `diff_cmd` to the default and retry to isolate the cause.","Validate your diff tool's output with `your-diff-cmd a b | diff - a.patch` style checks or feed it to `patch --dry-run` to confirm it's well-formed unified diff.","If the default setup fails, file a kitty issue including both files and the generated diff."],"exampleFix":"# before\ndiff_cmd custom-wrapper.sh\n\n# after\n# use default diff\n# (delete the diff_cmd line in kitty.conf)","handlingStrategy":"fallback","validationCode":"# shell: verify hunk arithmetic of your diff tool's output\n# GNU diff is the reference; compare hunk headers\nyour-diff-cmd a b > /tmp/xd\ndiff a b > /tmp/gd\nhead -100 /tmp/xd   # inspect @@ start,count @@ headers vs /tmp/gd","typeGuard":null,"tryCatchPattern":"Wrap finalize results; on a right/left side line mismatch, retry the whole diff with the default diff command, else report the malformed output to the user with the raw diff attached.","preventionTips":["Only use diff tools that emit spec-compliant unified diff.","Avoid exotic diff flags (--unified=0, word-diff) in diff_cmd.","Report parser bugs upstream with reproducing files."],"tags":["kitty","diff-kitten","diff-parsing","sanity-check"],"backgroundTag":"malformed-diff-output","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}