{"record":{"id":"647155e8f32862ab","repo":"kovidgoyal/kitty","slug":"malformed-cursor-position-report-from-terminal-s","errorCode":null,"errorMessage":"Malformed Cursor Position Report from terminal: %s","messagePattern":"Malformed Cursor Position Report from terminal: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/cli/wcswidth_kitten.go","lineNumber":32,"sourceCode":"\t\"github.com/kovidgoyal/kitty/tools/tui/loop\"\n\t\"github.com/kovidgoyal/kitty/tools/utils\"\n\t\"github.com/kovidgoyal/kitty/tools/utils/style\"\n\t\"github.com/kovidgoyal/kitty/tools/wcswidth\"\n)\n\nvar _ = fmt.Print\n\ntype cpos struct {\n\tx, y int\n}\n\nfunc cpos_from_report(csi string) (ans cpos, err error) {\n\tbefore, after, found := strings.Cut(csi, \";\")\n\tif !found {\n\t\treturn ans, fmt.Errorf(\"Malformed Cursor Position Report from terminal with no ;\")\n\t}\n\tif ans.y, err = strconv.Atoi(before); err != nil {\n\t\treturn ans, fmt.Errorf(\"Malformed Cursor Position Report from terminal: %s\", csi)\n\t}\n\tif ans.x, err = strconv.Atoi(after); err != nil {\n\t\treturn ans, fmt.Errorf(\"Malformed Cursor Position Report from terminal: %s\", csi)\n\t}\n\t// convert 1-based indexing to zero based indexing\n\tans.x--\n\tans.y--\n\treturn\n}\n\ntype test_struct struct {\n\tdescription               string\n\tnum                       int\n\texpected_cursor_positions []int\n\tactual_cursor_positions   []cpos\n\tpayload                   string\n\ttester                    func(actual_cursor_positions []cpos, screen_width int) string\n\tpayload_gen               func(width_in_cells int) string","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/tools/cli/wcswidth_kitten.go#L14-L50","documentation":"The terminal's cursor position report was split on ';' but the first half (the row) is not a valid integer. cpos_from_report uses strconv.Atoi on the row component and fails, meaning the report is malformed even though it contained a separator.","triggerScenarios":"A CPR response whose row field is non-numeric, e.g. \"\\x1b[abc;5R\", or a truncated/interleaved response where digits were lost or replaced by other escape sequence bytes.","commonSituations":"Terminal emulators or multiplexers that inject status lines or partial sequences into the input stream, latency/truncation of the tty read, or a non-conformant terminal responding to CSI 6n with unexpected data.","solutions":["Run in a known-conformant terminal without multiplexers","Verify no background process is writing to / reading from the controlling terminal","Update kitty to matching versions on both ends"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"before, _, _ := strings.Cut(csi, \";\")\nif _, err := strconv.Atoi(before); err != nil { /* skip report */ }","typeGuard":null,"tryCatchPattern":"if _, err := cpos_from_report(csi); err != nil { /* discard and re-query cursor position */ }","preventionTips":["Validate both numeric fields before using the report","Re-issue the CPR query on parse failure instead of proceeding"],"tags":["kitty","terminal","cpr","strconv"],"backgroundTag":"terminal-escape-sequence-parse-error","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}