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
- Call list_apps and use an exact name or pid from its output.
- Re-fetch the pid after an app restart — pids change on relaunch.
- If relying on the bound inputApp fallback, call open_application first.
- 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
- Never cache pids across app restarts; resolve via list_apps at use time.
- If no app_ref is passed, ensure open_application was called first so the fallback binding exists.
- Wait for an app to finish launching before querying its state.
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
- menu_item_not_found
- Agent not found
- Agent not found in the active session
- application window not found in UIA tree — pass…
- background preview capture failed
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)