Hmbown/CodeWhale · error
consent action must be status, allow, deny or revoke
Error message
consent action must be status, allow, deny or revoke (got ${JSON.stringify(args.action)}) What it means
Argument-validation guard in resolveTool for the 'consent' action: args.action matched none of status/allow/deny/revoke in the wire-name map, so the consent request cannot be mapped to a backend command. The bad value is echoed.
Solutions
- Use one of the four actions: status, allow, deny, revoke
- Lowercase the action value
- Map "grant" to "allow" and "block" to "deny" in caller code
Example fix
// before
resolveTool("consent", { action: "grant", app: "Notes" })
// after
resolveTool("consent", { action: "allow", app: "Notes" }) Defensive patterns
Strategy: validation
Validate before calling
if (!['status','allow','deny','revoke'].includes(args.action)) throw new Error('consent action must be status/allow/deny/revoke'); Type guard
function isConsentAction(a) { return ['status','allow','deny','revoke'].includes(a); } Try / catch
try { resolveTool('consent', args); } catch (e) { if (String(e.message).includes('consent action')) { /* map grant->allow, block->deny and retry */ } else throw e; } Prevention
- Normalize action casing
- Use the four canonical verbs only
- Check the schema's action enum before dispatch
When it happens
Trigger: resolveTool("consent", { action: "grant" }) or { action: "Allow" } or {} with no action.
Common situations: A model uses "grant"/"block" instead of allow/deny; missing action; case mismatch.
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 " " needs an app (name, bundle_id, pid or…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/a65fdfa05fedb66e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/src/tools.mjs:814
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];
if (!wire) throw bad(`consent action must be status, allow, deny or revoke (got ${JSON.stringify(args.action)})`);
if (args.action === "status") return { name: wire, args: { computer: rest.computer } };
const foreground = rest.scope === "foreground";
if (!foreground && rest.app == null && rest.name == null && rest.bundle_id == null && rest.pid == null) {
throw bad(`consent action "${args.action}" needs an app (name, bundle_id, pid or app string) — or scope:"foreground" for the shared-pointer decision`);
}
return { name: wire, args: rest };
}
case "key": {
if (args.duration == null) return { name, args };
const { duration, repeat, target, ...rest } = args;
if (repeat != null || target != null) throw bad("key with duration holds the key — repeat and target cannot be combined with it");
if (!Number.isFinite(duration) || duration < 0.05 || duration > 30) throw bad("duration must be 0.05..30 seconds");
return { name: "hold_key", args: { ...rest, duration } };
}
case "browser": {
const rest = { ...args };
delete rest.action;
switch (args.action) {View on GitHub (pinned to 73e0f67d83)