Hmbown/CodeWhale · error · ExecError
select_text needs an element target
Error message
select_text needs an element target — {type:'element',index} from get_app_state What it means
The macOS computer-use backend's select_text only accepts a semantic element target ({type:'element', index}) obtained from get_app_state. Passing a coordinate target, no target, or a target typed as something else is rejected with this ExecError so the request is not silently misinterpreted. It is a fail-fast argument contract check before delegating to the native bridge.
Solutions
- Call get_app_state first and pass {target:{type:'element', index:<i>}} using an index from that snapshot.
- If you only have coordinates, re-observe with get_app_state to resolve the element instead of guessing.
- Wrap the call in try/catch and fall back to get_app_state + retry when the target type is wrong.
Example fix
// before
await backend.select_text({ target: { type: 'coordinate', x: 120, y: 40 } });
// after
const state = await backend.get_app_state();
await backend.select_text({ target: { type: 'element', index: state.elements.findIndex(e => e.role === 'textArea') } }); Defensive patterns
Strategy: validation
Validate before calling
if (!args || args.target?.type !== 'element' || !Number.isInteger(args.target.index)) throw new TypeError('select_text requires {target:{type:"element", index}} from get_app_state'); Type guard
const isElementTarget = (t) => !!t && typeof t === 'object' && t.type === 'element' && Number.isInteger(t.index);
Try / catch
try { await backend.select_text(args); } catch (e) { if (String(e.message).includes('needs an element target')) { const s = await backend.get_app_state(); await backend.select_text({ target: { type: 'element', index: s.elements.findIndex(el => el.focused || el.role === 'textArea') } }); } else throw e; } Prevention
- Always call get_app_state immediately before element-targeted actions.
- Centralize element-target construction in a helper that asserts the shape.
- Never reuse coordinate targets for semantic actions.
When it happens
Trigger: Calling select_text({}) with no args, select_text({target:{type:'coordinate',...}}), select_text({target:{type:'text',...}}), or omitting target entirely on the darwin backend.
Common situations: Agents reusing a click-style coordinate target for select_text; tool callers copying args between select_text and coordinate-based actions; older code written before element targets were required.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- perform_action needs an element target
- Automation admission belongs to a different task store; it…
- Automation admission execution ownership is unverified or…
- Automation name is required
- Automation prompt is required
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ee0ac1dce144c280.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/src/backends/darwin.mjs:1182
const value = String(args.value ?? "");
await native("focus_element", { target: args.target });
// cmd+a through the record channel: menu key equivalents only
// validate against a key window, which the lease provides. bg_key
// posts a complete press (down and up); the `down` field is unused.
await native("bg_key", { code: 0, flags: 1 << 20 });
await new Promise((r) => setTimeout(r, 60));
await native("type", { text: value });
const back = await native("get_value", { target: args.target });
const verified = back?.value === value;
return { action_sent: true, strategy: "focus-type-replace", role: back?.role ?? null,
after: back?.value ?? null, verified,
...(verified ? {} : { note: "replacement did not verify against the control's own value; observe before relying on it" }) };
}
},
focus: (args = {}) => native("focus_element", args),
get_value: (args = {}) => native("get_value", args),
select_text: async (args = {}) => {
if (args.target?.type !== "element") throw new ExecError("select_text needs an element target — {type:'element',index} from get_app_state");
return native("select_text", args);
},
perform_action: async (args = {}) => {
if (args.target?.type !== "element") throw new ExecError("perform_action needs an element target — {type:'element',index} from get_app_state");
return native("perform_action", args);
},
invoke_menu: async ({ path: menuPath } = {}) => invokeMenu(menuPath),
app_script: appScript,
read_clipboard: readClipboard,
write_clipboard: writeClipboard,
cursor_position: cursorPosition,
recordingStart,
recordingStop,
recordingStatus,
recordingList,
closeSession,
list_sessions: async () => ({
via: "direct",View on GitHub (pinned to 73e0f67d83)