{"record":{"id":"108ce85d13a94a03","repo":"Hmbown/CodeWhale","slug":"the-selected-application-has-no-capturable-window-call-list","errorCode":null,"errorMessage":"the selected application has no capturable window — call list_windows","messagePattern":"the selected application has no capturable window — call list_windows","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/darwin.mjs","lineNumber":625,"sourceCode":"        }, timeoutMs);\n      })]);\n    } finally { clearTimeout(timer); }\n  }\n\n  async function recordingStart({ display, durationSec, region, app_ref, window_id } = {}) {\n    const dir = recordingsDir();\n    fs.mkdirSync(dir, { recursive: true });\n    const id = crypto.randomBytes(4).toString(\"hex\");\n    const file = path.join(dir, `rec-${id}.mov`);\n    const displays = await displayInfo();\n    // app_ref scopes the recording to the app's window rect: resolved once at\n    // start through the same window_info the AX path uses, so a background\n    // window records behind the user's work. The rect is fixed at start —\n    // it does not track later moves or resizes.\n    let window = null;\n    if (app_ref !== undefined || window_id != null) {\n      window = await native(\"window_info\", { app_ref: app_ref === undefined ? state.inputApp ?? undefined : app_ref, window_id });\n      if (!window?.points || !(window.points.w > 0) || !(window.points.h > 0)) throw new ExecError(\"the selected application has no capturable window — call list_windows\");\n      if (region) throw new ExecError(\"choose app_ref or region, not both\");\n      region = [window.points.x, window.points.y, window.points.w, window.points.h];\n    }\n    let disp = display ?? state.activeDisplay;\n    if (window && display == null) {\n      const cx = region[0] + region[2] / 2, cy = region[1] + region[3] / 2;\n      const host = displays.find(d => d.points && cx >= d.points.x && cx < d.points.x + d.points.w && cy >= d.points.y && cy < d.points.y + d.points.h);\n      if (host) disp = host.index;\n    }\n    const selected = displays.find(d => d.index === disp);\n    if (!selected) throw new ExecError(\"choose one available display for recording\");\n    if (durationSec != null && (!Number.isFinite(durationSec) || durationSec <= 0)) throw new ExecError(\"durationSec must be positive\");\n    const capabilities = await native(\"input_capabilities\");\n    if (capabilities?.record_owner_pipe !== 1) throw new ExecError(\"native screen recorder cannot own its client lifetime; update Computer Use before recording\");\n    const helper = await nativeHelper();\n    throwIfAborted();\n    const child = spawn(helper, [JSON.stringify({ tool: \"record\", args: { file, displayID: selected.id, region, durationSec, owner_pipe: true } })], { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n    child.stdin.on(\"error\", () => {});","sourceCodeStart":607,"sourceCodeEnd":643,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/darwin.mjs#L607-L643","documentation":"Before recording a specific application's window, the record action resolves the app via native window_info. If the resolved window has no points or a zero-width/height rect, there is nothing capturable to record and the library throws, directing the caller to list_windows.","triggerScenarios":"Calling record({ app_ref }) for an app with no on-screen windows (all minimized or only background windows); passing a window_id/app_ref that no longer exists; the app has a window whose rect reports zero size; stale app_ref after the target app quit.","commonSituations":"Target app is minimized to the Dock; targeting helper/background apps (menu-bar-only apps have no capturable window); the app crashed or was relaunched so the cached app_ref is stale.","solutions":["Call list_windows to get currently capturable windows and use a valid app_ref or window_id from it.","Un-minimize the target app or bring it on-screen so it has a non-zero window rect.","Record a display or region instead of an app window if the app has no GUI window.","Re-resolve app_ref after the target application was restarted."],"exampleFix":"// before\nawait record({ app_ref: staleRef });\n// after\nconst wins = await list_windows();\nawait record({ app_ref: wins[0].app_ref });","handlingStrategy":"fallback","validationCode":"const wins = await list_windows();\nconst target = wins.find(w => w.app_ref === appRef || w.window_id === windowId);\nif (!target || !target.points || !(target.points.w > 0) || !(target.points.h > 0))\n  throw new Error(\"target app has no capturable window\");","typeGuard":"const isCapturable = (w) => w?.points && w.points.w > 0 && w.points.h > 0;","tryCatchPattern":"try { await record({ app_ref }) } catch (e) {\n  if (String(e.message).includes(\"no capturable window\")) {\n    const wins = await list_windows();\n    if (wins.length) await record({ app_ref: wins[0].app_ref });\n  } else throw e;\n}","preventionTips":["Resolve app_ref/window_id fresh from list_windows before each recording.","Un-minimize the target app; minimized and menu-bar-only apps have no capturable window.","Fall back to display/region recording when no app window qualifies."],"tags":["macos","recording","window"],"backgroundTag":"entity-not-found","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}