{"record":{"id":"6d0f3c3c7a5ec53b","repo":"can1357/oh-my-pi","slug":"mouse-coordinates-must-be-non-negative-integers","errorCode":null,"errorMessage":"mouse coordinates must be non-negative integers","messagePattern":"mouse coordinates must be non-negative integers","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tui/src/debug-server.ts","lineNumber":185,"sourceCode":"\t\t\t\tliteral += source[offset++];\n\t\t\t}\n\t\t\tif (source[offset] !== quote) throw new Error(\"unterminated quoted key literal\");\n\t\t\toffset++;\n\t\t\tsequences.push(...Array.from(literal));\n\t\t\tevents += Array.from(literal).length;\n\t\t\tcontinue;\n\t\t}\n\t\tconst start = offset;\n\t\twhile (offset < source.length && !/\\s/.test(source[offset] ?? \"\")) offset++;\n\t\tsequences.push(encodeChord(source.slice(start, offset)));\n\t\tevents++;\n\t}\n\treturn { sequences, events };\n}\n\nfunction mouseSequence(x: number, y: number, action: string): string {\n\tif (!Number.isInteger(x) || !Number.isInteger(y) || x < 0 || y < 0)\n\t\tthrow new Error(\"mouse coordinates must be non-negative integers\");\n\tconst at = (button: number, release = false): string => `\\x1b[<${button};${x + 1};${y + 1}${release ? \"m\" : \"M\"}`;\n\tswitch (action) {\n\t\tcase \"click\":\n\t\t\treturn at(0) + at(0, true);\n\t\tcase \"right-click\":\n\t\t\treturn at(2) + at(2, true);\n\t\tcase \"middle-click\":\n\t\t\treturn at(1) + at(1, true);\n\t\tcase \"move\":\n\t\t\treturn at(35);\n\t\tcase \"drag\":\n\t\t\treturn at(32);\n\t\tcase \"release\":\n\t\t\treturn at(0, true);\n\t\tcase \"wheel-up\":\n\t\t\treturn at(64);\n\t\tcase \"wheel-down\":\n\t\t\treturn at(65);","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/tui/src/debug-server.ts#L167-L203","documentation":"mouseSequence() synthesizes SGR mouse escape sequences (\\x1b[<button;x;yM/m) for the debug server. Terminal coordinates must be non-negative integers; anything else would produce a malformed sequence, so it throws.","triggerScenarios":"Calling the mouse dispatch (via the debug server #dispatch path) with x or y negative, fractional, NaN, or non-integer — e.g. from a script computing coordinates with floats or -1 sentinels.","commonSituations":"Passing NaN from a failed number parse; using -1 as a 'click anywhere' sentinel; float math (e.g. percentages of terminal size) not rounded; JSON args where coordinates arrive as strings that were coerced badly.","solutions":["Validate and round coordinates before dispatch: Math.max(0, Math.round(x))","Fix the source of NaN/negative values (parse failures, sentinel values)","Use 0-based integer coordinates as the API expects (1 is added internally)"],"exampleFix":"// before\ndispatchMouse(x / 2, y / 2) // may be fractional\n// after\ndispatchMouse(Math.max(0, Math.round(x / 2)), Math.max(0, Math.round(y / 2)))","handlingStrategy":"validation","validationCode":"function validMouseCoords(x: unknown, y: unknown): x is number {\n  return Number.isInteger(x) && Number.isInteger(y) && (x as number) >= 0 && (y as number) >= 0;\n}","typeGuard":"function areValidCoords(x: unknown, y: unknown): x is number {\n  return typeof x === \"number\" && typeof y === \"number\" &&\n    Number.isInteger(x) && Number.isInteger(y) && x >= 0 && y >= 0;\n}","tryCatchPattern":"try {\n  dispatchMouse(x, y, action);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"non-negative integers\")) {\n    dispatchMouse(Math.max(0, Math.round(x)), Math.max(0, Math.round(y)), action);\n  } else throw err;\n}","preventionTips":["Round/sanitize any computed (float) coordinates before dispatching","Never use -1 or NaN as a coordinate sentinel","Validate external/JSON-supplied coordinates as integers >= 0 before dispatch"],"tags":["validation","mouse-input","debug"],"backgroundTag":"invalid-coordinate","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}