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

  1. Use button "left" with clicks 1, 2, or 3, or "right"/"middle" with clicks 1
  2. If a double-right-click is needed, issue two separate click calls with button:"right", clicks:1
  3. 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

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


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)