Hmbown/CodeWhale · error · NSException
invalid request
Error message
invalid request
What it means
The macOS accessibility computer-use backend is a helper binary that expects exactly one JSON argument and parses it with NSJSONSerialization. If the argument parses to something other than an NSDictionary (the top-level JSON object), the helper throws an 'invalid request' exception and fails instead of executing a command.
Solutions
- Pass exactly one argument containing the JSON request object, properly shell-quoted
- Ensure the JSON root is an object ({...}), not an array or scalar
- Rebuild/reinstall the native helper so binary and caller agree on the request format
- Test with a minimal payload like '{"args":{}}' to confirm the invocation works
Example fix
// before: unquoted / wrong shape
bin/darwin-accessibility args action=click
// after: one quoted JSON object argument
bin/darwin-accessibility '{"args":{"action":"click","x":100,"y":200}}' Defensive patterns
Strategy: validation
Validate before calling
function assertDarwinRequest(req) {
if (typeof req !== 'object' || req === null || Array.isArray(req))
throw new Error('darwin-accessibility request must be a JSON object');
}
// invocation: spawn(bin, [JSON.stringify(req)], ...) — one argument, always an object root Type guard
const isRequestObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
Try / catch
try {
const out = execFileSync(bin, [JSON.stringify(req)], { encoding: 'utf8' });
} catch (e) {
if (String(e.stderr || e.message).includes('invalid request')) {
// payload was not a single JSON object argument; fix invocation and retry
} else throw e;
} Prevention
- Always spawn the helper with exactly one argv entry: the stringified JSON object
- Validate the request is a plain object before serialization (not array/scalar)
- Quote JSON when testing the binary manually in a shell
- Keep the native helper and its caller version-locked; rebuild both together
When it happens
Trigger: Launching darwin-accessibility with zero, multiple, or malformed command-line arguments; passing JSON whose root is an array, string, or number instead of an object (argc!=2 raises the earlier 'args' exception; a non-dictionary root raises this one at line 840).
Common situations: Invoking the helper manually from a shell without quoting the JSON (shell splitting turns one arg into many); a caller passing JSON built with the wrong top-level shape; an old native binary being driven by a newer TUI that changed the request schema; quoting bugs that mangle the JSON payload.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- --input-json must be a JSON object
- missing
- Model response incomplete: provider stop reason
- %s
- A positive pull request number is required
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/dc4c5b6cd70d8f92.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/src/backends/darwin-accessibility.m:840
else if([tool isEqual:@"focus_element"]) e=AXUIElementSetAttributeValue((__bridge AXUIElementRef)el,kAXFocusedAttribute,kCFBooleanTrue);
else if([tool isEqual:@"select_text"]){ NSArray *r=args[@"text_range"]?:@[@0,@0]; if(r.count!=2 || [r[0] longValue]<0 || [r[1] longValue]<0) @throw [NSException exceptionWithName:@"range" reason:@"text_range must be [start, length], both nonnegative" userInfo:nil]; CFRange range=CFRangeMake([r[0] longValue],[r[1] longValue]); AXValueRef v=AXValueCreate(kAXValueCFRangeType,&range); e=AXUIElementSetAttributeValue((__bridge AXUIElementRef)el,kAXSelectedTextRangeAttribute,v); CFRelease(v); }
else if([tool isEqual:@"perform_action"]){ CFArrayRef actions=NULL; AXUIElementCopyActionNames((__bridge AXUIElementRef)el,&actions); NSArray *names=CFBridgingRelease(actions); if(![names containsObject:args[@"action"]]) @throw [NSException exceptionWithName:@"action" reason:@"action is not advertised by this element" userInfo:nil]; cuCheckCancelled(); e=AXUIElementPerformAction((__bridge AXUIElementRef)el,(__bridge CFStringRef)args[@"action"]); }
if(e!=kAXErrorSuccess) @throw [NSException exceptionWithName:@"action" reason:[NSString stringWithFormat:@"accessibility action failed: %d",e] userInfo:nil];
NSMutableDictionary *done=[@{@"action_sent":@YES,@"strategy":@"a11y"} mutableCopy];
if([tool isEqual:@"focus_element"]) done[@"focused"]=@YES;
if([tool isEqual:@"set_value"]) {
id after=attr((__bridge AXUIElementRef)el,@"AXValue");
done[@"after"]=after?:[NSNull null];
done[@"verified"]=@([after isKindOfClass:NSString.class] && [after isEqual:args[@"value"]]);
}
return done;
} @finally { CFRelease(app); }
}
int main(int argc, const char **argv){ @autoreleasepool {
signal(SIGTERM,cuCancel); signal(SIGINT,cuCancel); signal(SIGPIPE,SIG_IGN);
@try { if(argc!=2) @throw [NSException exceptionWithName:@"args" reason:@"expected one JSON argument" userInfo:nil];
NSError *error=nil; id p=[NSJSONSerialization JSONObjectWithData:[[NSString stringWithUTF8String:argv[1]] dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error];
if(![p isKindOfClass:NSDictionary.class]) @throw [NSException exceptionWithName:@"json" reason:@"invalid request" userInfo:nil];
id result=execute(p);
if([p[@"args"][@"input_lease"] boolValue]) { NSMutableDictionary *ack=[result mutableCopy]; ack[@"input_lease"]=@YES; result=ack; }
NSData *data=[NSJSONSerialization dataWithJSONObject:result options:NSJSONWritingFragmentsAllowed error:&error];
if(!data) @throw [NSException exceptionWithName:@"json" reason:error.localizedDescription userInfo:nil];
puts([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding].UTF8String); fflush(stdout);
if([p[@"args"][@"input_lease"] boolValue]) cuWaitForLease();
return 0;
} @catch(NSException *e){ cuReleaseLease(); fprintf(stderr,"%s\n",e.reason.UTF8String); return 1; }
} }
View on GitHub (pinned to 433685b202)