Hmbown/CodeWhale · error

recording action must be start, stop, status or list

Error message

recording action must be start, stop, status or list (got ${JSON.stringify(args.action)})

What it means

Argument-validation guard in the computer-use plugin's resolveTool for the 'recording' action: args.action did not match any of start/stop/status/list in the action-to-wire-name map, so no backend command could be resolved. The offending value is echoed in the message.

Solutions

  1. Use one of the supported actions: start, stop, status, list
  2. Fix casing to lowercase
  3. Drop unsupported operations — there is no pause/resume; stop then start a new recording

Example fix

// before
resolveTool("recording", { action: "pause" })
// after
resolveTool("recording", { action: "stop", id: "rec1" })
Defensive patterns

Strategy: validation

Validate before calling

if (!['start','stop','status','list'].includes(args.action)) throw new Error('recording action must be start/stop/status/list');

Type guard

function isRecordingAction(a) { return ['start','stop','status','list'].includes(a); }

Try / catch

try { resolveTool('recording', args); } catch (e) { if (String(e.message).includes('recording action')) { /* correct the action and retry */ } else throw e; }

Prevention

When it happens

Trigger: resolveTool("recording", { action: "pause" }) or { action: "Start" } or {} with no action at all.

Common situations: A model tries a "pause"/"resume" action that does not exist; action field omitted; wrong casing like "Stop".

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/9ea647a05a099d2e. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/plugins/computer-use/src/tools.mjs:795

      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 } };
      }
      throw bad(`clipboard action must be "read" or "write" (got ${JSON.stringify(args.action)})`);
    }
    case "recording": {
      const rest = { ...args };
      delete rest.action;
      const wire = { start: "recording_start", stop: "recording_stop", status: "recording_status", list: "recording_list" }[args.action];
      if (!wire) throw bad(`recording action must be start, stop, status or list (got ${JSON.stringify(args.action)})`);
      if ((args.action === "stop" || args.action === "status") && rest.id == null) throw bad(`recording action "${args.action}" requires id`);
      return { name: wire, args: rest };
    }
    case "computer": {
      const rest = { ...args };
      delete rest.action;
      const wire = { list: "computer_list", switch: "computer_switch", register: "computer_register", spawn: "computer_spawn", remove: "computer_remove" }[args.action];
      if (!wire) throw bad(`computer action must be list, switch, register, spawn or remove (got ${JSON.stringify(args.action)})`);
      if (args.action === "list") return { name: wire, args: {} };
      if (rest.id == null) throw bad(`computer action "${args.action}" requires id`);
      const id = rest.id;
      delete rest.id;
      return { name: wire, args: { ...rest, computer: id } };
    }
    case "consent": {
      const rest = { ...args };
      delete rest.action;
      const wire = { status: "consent_status", allow: "consent_allow", deny: "consent_deny", revoke: "consent_revoke" }[args.action];

View on GitHub (pinned to 73e0f67d83)