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

  1. Call get_app_state first and pass {target:{type:'element', index:<i>}} using an index from that snapshot.
  2. If you only have coordinates, re-observe with get_app_state to resolve the element instead of guessing.
  3. 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

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


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)