Hmbown/CodeWhale · error
click supports left with 1-3 clicks, right x1 or middle x1
Error message
click supports left with 1-3 clicks, right x1 or middle x1 (got ${JSON.stringify(button)} x${clicks}) What it means
The computer-use plugin's `click` tool resolver maps a high-level click spec (button + clicks) onto a wire protocol tool name. It only supports left with 1-3 clicks, right x1, or middle x1; any other combination is rejected with this error because no corresponding wire tool exists.
Solutions
- Use button "left" with clicks 1, 2, or 3, or "right"/"middle" with clicks 1
- If a double-right-click is needed, issue two separate click calls with button:"right", clicks:1
- Fix the caller to send the button as a lowercase string "left"|"right"|"middle", not a number or alias
Example fix
// before
resolveTool("click", { button: "right", clicks: 2 })
// after
resolveTool("click", { button: "right", clicks: 1 }) // issued twice, or left/double-click if that was meant Defensive patterns
Strategy: validation
Validate before calling
const CLICKS = { left: [1,2,3], right: [1], middle: [1] };
function validClick(args) { return CLICKS[args.button]?.includes(args.clicks) ?? false; }
if (!validClick(args)) throw new Error(`bad click spec: ${JSON.stringify(args)}`); Type guard
function isClickSpec(a) { return (a.button === 'left' && [1,2,3].includes(a.clicks)) || ((a.button === 'right' || a.button === 'middle') && a.clicks === 1); } Prevention
- Coerce/normalize button and clicks to canonical string/number types before calling
- Keep a lookup table of valid button/clicks combinations in the caller
- Split multi-click right/middle actions into repeated single-click calls
When it happens
Trigger: Calling resolveTool for tool "click" with e.g. button:"right" and clicks:2, button:"middle" and clicks:2, button:"triple", or clicks:0/4 with any button — any combination not in the wire mapping table.
Common situations: An LLM or automation script emits double-right-click or quadruple-left-click; a UI wrapper passes a numeric button code instead of "left"/"right"/"middle"; a model hallucinates a button name like "primary".
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- pointer action must be "move", "down" or "up
- --attempts must be an integer from 1 to 20
- --channel, --version and --reason are required
- Choose one Runtime --thread ID.
- Command is required
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ae13a93e35d40d58.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/src/tools.mjs:770
* fails as bad_args with the requested name. Unknown names pass through
* unchanged — the alias surface is the rest of TOOLS.
*/
export function resolveTool(name, args = {}) {
const bad = (message) => Object.assign(new Error(message), { code: "bad_args" });
switch (name) {
case "click": {
const button = args.button ?? "left";
const clicks = args.clicks ?? 1;
const rest = { ...args };
delete rest.button;
delete rest.clicks;
const wire = button === "left" && clicks === 1 ? "left_click"
: button === "left" && clicks === 2 ? "double_click"
: button === "left" && clicks === 3 ? "triple_click"
: button === "right" && clicks === 1 ? "right_click"
: button === "middle" && clicks === 1 ? "middle_click"
: null;
if (!wire) throw bad(`click supports left with 1-3 clicks, right x1 or middle x1 (got ${JSON.stringify(button)} x${clicks})`);
if (button !== "left") delete rest.strategy; // strategy is an a11y-left-click concept
return { name: wire, args: rest };
}
case "pointer": {
const rest = { ...args };
delete rest.action;
const wire = { move: "mouse_move", down: "left_mouse_down", up: "left_mouse_up" }[args.action];
if (!wire) throw bad(`pointer action must be "move", "down" or "up" (got ${JSON.stringify(args.action)})`);
return { name: wire, args: rest };
}
case "clipboard": {
const rest = { ...args };
delete rest.action;
if (args.action === "read") return { name: "read_clipboard", args: { computer: rest.computer } };
if (args.action === "write") {
if (typeof rest.text !== "string") throw bad("clipboard action \"write\" requires text");
return { name: "write_clipboard", args: { text: rest.text, computer: rest.computer } };
}View on GitHub (pinned to 73e0f67d83)