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
- Use one of the supported actions: start, stop, status, list
- Fix casing to lowercase
- 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
- Normalize action casing
- Model pause/resume as stop + start, not new actions
- Validate against the enum before dispatch
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
- agent profile reasoning_effort must be one of: inherit…
- Choose approve or decline
- clipboard action must be "read" or "write
- computer action must be list, switch, register, spawn or…
- consent action must be status, allow, deny or revoke
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)