{"record":{"id":"650f16492ffe7dac","repo":"Hmbown/CodeWhale","slug":"no-display-index-have-ds-map-d-d-index-join","errorCode":null,"errorMessage":"no display ${index}; have [${ds.map((d) => d.index).join(\", \")}]","messagePattern":"no display (.+?); have \\[(.+?)\\]","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"warning","filePath":"crates/tui/plugins/computer-use/src/backends/darwin.mjs","lineNumber":931,"sourceCode":"    caps.raw_input = caps.accessibility_tree;\n    try {\n      const t = os.tmpdir() + `/cu-probe-${crypto.randomBytes(3).toString(\"hex\")}.png`;\n      const r = await runL(\"screencapture\", [\"-x\", \"-R0,0,2,2\", \"-t\", \"png\", t], { timeoutMs: 8_000 });\n      perms.screen_capture = r.code === 0 ? \"ok\" : \"failed\";\n      try { fs.rmSync(t, { force: true }); } catch {}\n    } catch { perms.screen_capture = \"failed\"; }\n    caps.screenshot = perms.screen_capture === \"ok\";\n    caps.recording = caps.screenshot;\n    return { platform: \"darwin\", capabilities: caps, permissions: perms, note: \"macOS does not expose Screen-Recording TCC state to CLI; a black/empty screenshot means Screen Recording permission is missing. Background mode (open_application activate:false) uses process-bound keyboard events and accessibility actions; shared pointer gestures are refused. Foreground control (activate:true) uses the shared desktop and requires exclusive use. Neither mode is an isolated desktop. App-specific behavior still requires verification.\" };\n  }\n\n  return {\n    platform: \"darwin\",\n    probe,\n    list_displays: displayInfo,\n    async switch_display({ index }) {\n      const ds = await displayInfo();\n      if (!ds.some((d) => d.index === index)) throw new ExecError(`no display ${index}; have [${ds.map((d) => d.index).join(\", \")}]`);\n      state.activeDisplay = index;\n      return { activeDisplay: index };\n    },\n    list_apps: listApps,\n    set_window_frame: async ({ app_ref, window_id, frame } = {}) => {\n      if (!frame || !Number.isFinite(frame.x) || !Number.isFinite(frame.y) || !Number.isFinite(frame.w) || !Number.isFinite(frame.h) || frame.w <= 0 || frame.h <= 0) {\n        throw Object.assign(new ExecError(\"set_window_frame needs frame {x,y,w,h} with positive w/h\"), { code: \"bad_args\" });\n      }\n      if (!Number.isSafeInteger(window_id) || window_id < 0) {\n        throw Object.assign(new ExecError(\"set_window_frame needs window_id (a non-negative window index from list_windows)\"), { code: \"bad_args\" });\n      }\n      const r = await native(\"set_window_frame\", { app_ref, window_id, frame });\n      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\" };\n    },\n    list_windows: listWindows,\n    open_application: openApplication,\n    get_app_state: async ({ app_ref, detail, depth, window_id, include_ocr = false, ocr_region } = {}) => {\n      const t0 = Date.now();","sourceCodeStart":913,"sourceCodeEnd":949,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/darwin.mjs#L913-L949","documentation":"switch_display validates the requested display index against the currently enumerated displays (from displayInfo/list_displays); if no display has that index it throws, listing the valid indices. Indices are re-enumerated on every call, so the set reflects current hardware state.","triggerScenarios":"Calling switch_display with an index that does not exist — a 0-based vs 1-based confusion, an index from a previous session whose monitor setup changed, or an index hallucinated without calling list_displays.","commonSituations":"Docking-station changes removing a second display; scripts hardcoded to a two-monitor setup run on a single-monitor machine; off-by-one errors between display numbering conventions.","solutions":["Call list_displays and use one of the indices it returns (the error message lists them too).","Handle the error and fall back to the first available display when the requested one is gone.","Re-verify displays after hardware changes (dock connect/disconnect, sleep/wake) before switching."],"exampleFix":"// before\nawait backend.switchDisplay({ index: 2 });\n// after\nconst ds = await backend.listDisplays();\nif (ds.some(d => d.index === 2)) await backend.switchDisplay({ index: 2 });","handlingStrategy":"validation","validationCode":"const ds = await backend.listDisplays();\nif (!ds.some(d => d.index === index)) throw new Error(`display ${index} not available; have ${ds.map(d => d.index)}`);","typeGuard":null,"tryCatchPattern":"try {\n  await backend.switchDisplay({ index });\n} catch (e) {\n  if (String(e.message).startsWith('no display')) {\n    const ds = await backend.listDisplays();\n    if (ds.length) await backend.switchDisplay({ index: ds[0].index });\n  } else throw e;\n}","preventionTips":["Always enumerate displays immediately before switching.","Re-enumerate after dock/hardware changes or system wake.","Don't hardcode indices — pick from list_displays output."],"tags":["display","out-of-range","macos"],"backgroundTag":"index-out-of-range","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"}