Hmbown/CodeWhale · error · ExecError

application not found — call list_apps for exact names/pids

Error message

application not found — call list_apps for exact names/pids

What it means

get_app_state resolves app_ref (falling back to the bound inputApp) through the native layer and returns a found flag; when the native lookup reports the application could not be found, the library throws this error directing the caller to list_apps for valid identities.

Solutions

  1. Call list_apps and use an exact name or pid from its output.
  2. Re-fetch the pid after an app restart — pids change on relaunch.
  3. If relying on the bound inputApp fallback, call open_application first.
  4. Confirm the app is actually running (e.g. open_application can launch it by bundle_id).

Example fix

// before
const state = await backend.getAppState({ pid: 1234 }); // stale pid
// after
const apps = await backend.listApps();
const app = apps.find(a => a.name === "Safari");
const state = await backend.getAppState({ pid: app.pid });
Defensive patterns

Strategy: validation

Validate before calling

const apps = await backend.listApps();
const target = apps.find(a => a.name === appName || a.pid === pid);
if (!target) throw new Error(`${appName} is not running`);

Try / catch

try {
  const st = await backend.getAppState({ app_ref });
} catch (e) {
  if (String(e.message).startsWith('application not found')) {
    const apps = await backend.listApps(); // refresh identities and retry
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a pid of a process that has exited; a name/bundle_id that does not match any running app; omitting app_ref when no application has been bound via open_application; a 32-bit/removed app or permission-restricted process invisible to the accessibility API.

Common situations: Automating an app that crashed or was relaunched with a new pid between calls; app names differing from their display names; a freshly installed app not yet running; race between launching an app and querying its state.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

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

    },
    list_apps: listApps,
    set_window_frame: async ({ app_ref, window_id, frame } = {}) => {
      if (!frame || !Number.isFinite(frame.x) || !Number.isFinite(frame.y) || !Number.isFinite(frame.w) || !Number.isFinite(frame.h) || frame.w <= 0 || frame.h <= 0) {
        throw Object.assign(new ExecError("set_window_frame needs frame {x,y,w,h} with positive w/h"), { code: "bad_args" });
      }
      if (!Number.isSafeInteger(window_id) || window_id < 0) {
        throw Object.assign(new ExecError("set_window_frame needs window_id (a non-negative window index from list_windows)"), { code: "bad_args" });
      }
      const r = await native("set_window_frame", { app_ref, window_id, frame });
      return { ...r, verified: r?.verified === true, note: r?.note ?? "the after frame is the app's own readback; cross-check with list_windows before relying on it" };
    },
    list_windows: listWindows,
    open_application: openApplication,
    get_app_state: async ({ app_ref, detail, depth, window_id, include_ocr = false, ocr_region } = {}) => {
      const t0 = Date.now();
      const t = await native("get_app_state", { app_ref: app_ref === undefined ? state.inputApp ?? undefined : app_ref, detail, window_id });
      if (process.env.CODEWHALE_CU_DEBUG_OBSERVE) console.error(`observe ${Date.now() - t0}ms elements=${t.elements?.length} truncated=${t.truncated}`);
      if (!t.found) throw new ExecError("application not found — call list_apps for exact names/pids");
      if (include_ocr) {
        // Resolve once through AX, then capture only that exact application's
        // selected window. A changing foreground cannot redirect this image.
        let raster;
        try {
          if (!Number.isSafeInteger(t.pid) || t.pid <= 0) throw new ExecError("The observed application did not provide an exact process identity for OCR");
          if ((await native("input_capabilities"))?.window_ocr !== 1) throw new ExecError("The native helper needs an update for selected-window text recognition");
          // PNG here, against the JPEG default: this raster is fed to text
          // recognition, not to a viewer, and lossless glyph edges are what
          // Vision reads. A single window is small enough that the size the
          // JPEG default exists to solve does not arise.
          const ocrDir = path.join(recordingsDir(), "captures");
          fs.mkdirSync(ocrDir, { recursive: true });
          raster = await screenshot({
            ...(ocr_region
              ? { region: ocr_region }
              : { app_ref: { pid: t.pid, ...(t.bundle_id ? { bundle_id: t.bundle_id } : {}) }, window_id }),
            path: path.join(ocrDir, `ocr-${crypto.randomBytes(4).toString("hex")}.png`),

View on GitHub (pinned to 73e0f67d83)