Hmbown/CodeWhale · warning · ExecError
no display ; have [ ]
Error message
no display ${index}; have [${ds.map((d) => d.index).join(", ")}] What it means
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.
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.
Example fix
// before
await backend.switchDisplay({ index: 2 });
// after
const ds = await backend.listDisplays();
if (ds.some(d => d.index === 2)) await backend.switchDisplay({ index: 2 }); Defensive patterns
Strategy: validation
Validate before calling
const ds = await backend.listDisplays();
if (!ds.some(d => d.index === index)) throw new Error(`display ${index} not available; have ${ds.map(d => d.index)}`); Try / catch
try {
await backend.switchDisplay({ index });
} catch (e) {
if (String(e.message).startsWith('no display')) {
const ds = await backend.listDisplays();
if (ds.length) await backend.switchDisplay({ index: ds[0].index });
} else throw e;
} Prevention
- Always enumerate displays immediately before switching.
- Re-enumerate after dock/hardware changes or system wake.
- Don't hardcode indices — pick from list_displays output.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- choose one available display for recording
- application not found — call list_apps for exact names/pids
- background preview capture failed
- display index is out of range
- display index must be a positive integer
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/650f16492ffe7dac.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/src/backends/darwin.mjs:931
caps.raw_input = caps.accessibility_tree;
try {
const t = os.tmpdir() + `/cu-probe-${crypto.randomBytes(3).toString("hex")}.png`;
const r = await runL("screencapture", ["-x", "-R0,0,2,2", "-t", "png", t], { timeoutMs: 8_000 });
perms.screen_capture = r.code === 0 ? "ok" : "failed";
try { fs.rmSync(t, { force: true }); } catch {}
} catch { perms.screen_capture = "failed"; }
caps.screenshot = perms.screen_capture === "ok";
caps.recording = caps.screenshot;
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." };
}
return {
platform: "darwin",
probe,
list_displays: displayInfo,
async switch_display({ index }) {
const ds = await displayInfo();
if (!ds.some((d) => d.index === index)) throw new ExecError(`no display ${index}; have [${ds.map((d) => d.index).join(", ")}]`);
state.activeDisplay = index;
return { activeDisplay: index };
},
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();View on GitHub (pinned to 73e0f67d83)