can1357/oh-my-pi · error

mouse coordinates must be non-negative integers

Error message

mouse coordinates must be non-negative integers

What it means

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.

Source

Thrown at packages/tui/src/debug-server.ts:185

				literal += source[offset++];
			}
			if (source[offset] !== quote) throw new Error("unterminated quoted key literal");
			offset++;
			sequences.push(...Array.from(literal));
			events += Array.from(literal).length;
			continue;
		}
		const start = offset;
		while (offset < source.length && !/\s/.test(source[offset] ?? "")) offset++;
		sequences.push(encodeChord(source.slice(start, offset)));
		events++;
	}
	return { sequences, events };
}

function mouseSequence(x: number, y: number, action: string): string {
	if (!Number.isInteger(x) || !Number.isInteger(y) || x < 0 || y < 0)
		throw new Error("mouse coordinates must be non-negative integers");
	const at = (button: number, release = false): string => `\x1b[<${button};${x + 1};${y + 1}${release ? "m" : "M"}`;
	switch (action) {
		case "click":
			return at(0) + at(0, true);
		case "right-click":
			return at(2) + at(2, true);
		case "middle-click":
			return at(1) + at(1, true);
		case "move":
			return at(35);
		case "drag":
			return at(32);
		case "release":
			return at(0, true);
		case "wheel-up":
			return at(64);
		case "wheel-down":
			return at(65);

View on GitHub (pinned to 9690622007)

Solutions

  1. Validate and round coordinates before dispatch: Math.max(0, Math.round(x))
  2. Fix the source of NaN/negative values (parse failures, sentinel values)
  3. Use 0-based integer coordinates as the API expects (1 is added internally)

Example fix

// before
dispatchMouse(x / 2, y / 2) // may be fractional
// after
dispatchMouse(Math.max(0, Math.round(x / 2)), Math.max(0, Math.round(y / 2)))
Defensive patterns

Strategy: validation

Validate before calling

function validMouseCoords(x: unknown, y: unknown): x is number {
  return Number.isInteger(x) && Number.isInteger(y) && (x as number) >= 0 && (y as number) >= 0;
}

Type guard

function areValidCoords(x: unknown, y: unknown): x is number {
  return typeof x === "number" && typeof y === "number" &&
    Number.isInteger(x) && Number.isInteger(y) && x >= 0 && y >= 0;
}

Try / catch

try {
  dispatchMouse(x, y, action);
} catch (err) {
  if (err instanceof Error && err.message.includes("non-negative integers")) {
    dispatchMouse(Math.max(0, Math.round(x)), Math.max(0, Math.round(y)), action);
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/6d0f3c3c7a5ec53b. Report an issue: GitHub.