Hmbown/CodeWhale · error · ExecError

shared_pointer_required

shared_pointer_required

Error message

This action needs the shared macOS pointer and was not sent in background mode. Use an accessibility action or a separate computer; foreground control requires exclusive desktop use authorized by the user.

What it means

Some macOS pointer actions (global gestures like drags) need the shared hardware pointer, and requireSharedPointer only permits them when the session runs in background/shared mode (state.foregroundInput set). In foreground mode the backend has been authorized for exclusive desktop use; refusing here prevents the agent from hijacking the user's only pointer without that authorization.

Solutions

  1. Re-open the session in background/shared mode (set the background_input/foreground option appropriately when calling open_application) so shared-pointer actions are allowed.
  2. Replace the gesture with an accessibility element action (AXPress etc.) which doesn't need the shared pointer.
  3. Run the target on a separate computer/virtual display so the shared pointer is genuinely free.
  4. If foreground control is truly intended, obtain explicit user authorization for exclusive desktop use and start the session in foreground mode.

Example fix

// before
await open_application(app, { foreground: true });
await pointer_sequence({ actions: [drag...] }); // shared_pointer_required

// after
await open_application(app, { background: true });
await pointer_sequence({ actions: [drag...] });
Defensive patterns

Strategy: validation

Validate before calling

// before shared-pointer gestures, confirm the session allows them
if (!sessionState.foregroundInput && wantsSharedPointer) {
  throw new Error('open the session in background/shared mode first');
}

Try / catch

try {
  await pointer_sequence(drag);
} catch (e) {
  if (e?.code === 'shared_pointer_required') {
    // switch to accessibility action instead of hijacking the pointer
    await a11yAction(target, 'AXPress');
  } else throw e;
}

Prevention

When it happens

Trigger: Invoking a shared-pointer tool (e.g. pointer_sequence — nativeLease calls requireSharedPointer for it) while the session was opened with foreground/exclusive input instead of background mode, i.e. state.foregroundInput is false.

Common situations: Running the agent directly on the user's desktop (foreground session) and then attempting a drag; misconfigured session options that left background mode off; scripts written for a remote/separate-computer setup run locally in foreground mode.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/c6c38024e0e557a7. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/plugins/computer-use/src/backends/darwin.mjs:367

  // ---------- pointer input ----------
  // Our qualified raw pointer path uses the shared event tap, which moves
  // the user's real cursor. Process/window-directed mouse delivery has not
  // passed the independent fixture. So the pointer path is:
  //   1. accessibility action on the element under the point (quiet, exact),
  //   2. otherwise refuse in background mode. Explicit foreground control
  //      permits a global gesture only when the bound application owns the
  //      window under the point. Restoring the cursor is not isolation.
  // Every receipt says which of the two happened.
  function mouseName(button) { return { left: "left", right: "right", middle: "middle" }[button] ?? "left"; }

  function assertInScreen(x, y) {
    if (!Number.isFinite(x) || !Number.isFinite(y)) throw new ExecError("coordinates must be finite numbers");
  }

  function buttonCode(button) { return button === "middle" ? 2 : button === "right" ? 1 : 0; }

  function requireSharedPointer() {
    if (!state.foregroundInput) throw Object.assign(new ExecError("This action needs the shared macOS pointer and was not sent in background mode. Use an accessibility action or a separate computer; foreground control requires exclusive desktop use authorized by the user."), { code: "shared_pointer_required" });
  }

  /** Refuse a global gesture whose landing point belongs to another application. */
  async function assertOwnsPoint(x, y) {
    if (!state.inputApp) throw new ExecError("open_application first to choose which application receives input");
    const w = await native("window_at_point", { x, y });
    if (!w?.found) throw new ExecError(`no window at (${x}, ${y}) — take a fresh screenshot and choose a point inside the target window`);
    if (w.owner_pid !== state.inputApp.pid) {
      throw new ExecError(`(${x}, ${y}) is covered by a window owned by ${w.owner_name || "another application"} (pid ${w.owner_pid}) — use an accessibility element target or a separate computer; no pointer input was sent`);
    }
    return w;
  }

  /** What a global gesture cost the user: their cursor, and briefly their foreground. */
  function pointerCost(r) {
    return {
      pointer_moved: true,
      pointer_restored: !!r?.restored,

View on GitHub (pinned to 73e0f67d83)