{"record":{"id":"6cc0226efef896d2","repo":"Hmbown/CodeWhale","slug":"harmony-backend-exposes-display-1-only","errorCode":null,"errorMessage":"harmony backend exposes display 1 only","messagePattern":"harmony backend exposes display 1 only","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/harmonyos.mjs","lineNumber":168,"sourceCode":"        connected,\n        targets,\n        capabilities: { screenshot: connected, accessibility_tree: connected, clipboard: false, recording: \"snapshot-series\" },\n        note: \"HarmonyOS drives the device over hdc. Clipboard read/write is not exposed by hdc and fails closed. Recording muxes snapshot_display frames with ffmpeg.\",\n      };\n    },\n    list_displays: async () => {\n      if (!displayPixels) {\n        const dir = fs.mkdtempSync(path.join(os.tmpdir(), \"cu-hm-\"));\n        try {\n          const shot = path.join(dir, \"probe.jpeg\");\n          await snapshot(shot);\n          displayPixels = jpegSize(fs.readFileSync(shot)) ?? { w: null, h: null };\n        } finally { fs.rmSync(dir, { recursive: true, force: true }).catch(() => {}); }\n      }\n      return [{ index: 1, name: \"device\", pixels: displayPixels, points: displayPixels, scale: 1, main: true }];\n    },\n    async switch_display({ index }) {\n      if (index !== 1) throw new ExecError(\"harmony backend exposes display 1 only\");\n      return { activeDisplay: 1 };\n    },\n    list_apps: async () => {\n      const out = await deviceOut([\"bm\", \"dump\", \"-a\"], { timeoutMs: 25_000 });\n      const bundles = out.split(\"\\n\").map((s) => s.trim()).filter((s) => /^[a-zA-Z][\\w.]*$/.test(s));\n      return { apps: bundles.map((b) => ({ name: b, bundle_id: b, kind: \"bundle\" })) };\n    },\n    list_windows: async (args = {}) => {\n      rejectAppSelectors(args);\n      const out = await deviceOut([\"hidumper\", \"-s\", \"WindowManagerService\", \"-a\", \"-a\"], { timeoutMs: 25_000 }).catch(() => \"\");\n      const windows = out.split(\"\\n\").filter((l) => /Window Name|bundleName/i.test(l)).slice(0, 40).map((l) => ({ title: l.trim().slice(0, 160) }));\n      return { windows: windows.length ? windows : [{ title: \"(window list unavailable on this HarmonyOS build)\" }] };\n    },\n    open_application: async ({ bundle_id: bid, ability, name } = {}) => {\n      const bundle = bid ?? name;\n      const identifier = (value) => typeof value === \"string\" && value.length <= 256 && /^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(value);\n      if (!identifier(bundle)) throw new ExecError(\"open_application needs a valid Harmony bundle identifier\");\n      if (ability != null && !identifier(ability)) throw new ExecError(\"open_application needs a valid Harmony ability identifier\");","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/harmonyos.mjs#L150-L186","documentation":"switch_display on the HarmonyOS backend fails because the backend only exposes display 1: displays are enumerated from a snapshot_display probe and hdc offers a single display surface, so any other requested display index is rejected.","triggerScenarios":"Calling switch_display({index: 0}) or any index other than 1 on the harmonyos backend.","commonSituations":"Code written for multi-display macOS backends using 0-based display indexes; enumerating displays generically and switching to the 'first' one (index 0); ported automation scripts assuming multiple monitors.","solutions":["Pass index: 1, the only display this backend exposes.","Skip switch_display entirely — the single device display is already active.","Gate display-switching logic on backend type or on list_displays() results."],"exampleFix":"// before\nawait backend.switch_display({ index: 0 });\n// after\nconst displays = await backend.list_displays();\nif (displays.length > 1) await backend.switch_display({ index: displays[0].index }); // index 1 on harmonyos","handlingStrategy":"validation","validationCode":"if (index !== 1) throw new TypeError('harmony backend exposes display 1 only');","typeGuard":"const isHarmonyDisplay = (i) => i === 1;","tryCatchPattern":"try { await backend.switch_display({ index }); } catch (e) { if (String(e.message).includes('display 1 only')) { /* single-display device; stay on display 1 */ } else throw e; }","preventionTips":["Check list_displays() before switching.","Skip display switching on single-display (harmonyos) backends.","Avoid hardcoding 0-based display indexes in cross-platform scripts."],"tags":["harmonyos","display","unsupported-operation"],"backgroundTag":"value-out-of-range","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T21:17:16.096Z"}