{"record":{"id":"a9f8e39a1e62ef7f","repo":"Hmbown/CodeWhale","slug":"clipboard-read-failed","errorCode":null,"errorMessage":"clipboard read failed","messagePattern":"clipboard read failed","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/linux.mjs","lineNumber":748,"sourceCode":"    if match is None and want == \"click\":\n        match = next((n for n in names if n.lower() in (\"click\", \"press\", \"activate\")), None)\n    if match is None:\n        print(json.dumps({\"ok\": False, \"code\": \"action_not_found: \" + \",\".join(names)}))\n    else:\n        a.doAction(names.index(match))\n        print(json.dumps({\"ok\": True, \"sent\": True}))`;\n      const out = await atspiResolve(target, body, String(action));\n      if (!out.ok) throw new ExecError(`perform_action failed: ${out.code}`);\n      return { action_sent: true, strategy: \"a11y\", action };\n    },\n    read_clipboard: async () => {\n      await probeSession();\n      const cmd = session === \"x11\"\n        ? (tools.xclip ? [\"xclip\", \"-selection\", \"clipboard\", \"-o\"] : [\"xsel\", \"--clipboard\", \"--output\"])\n        : [\"wl-paste\"];\n      need(cmd[0], \"clipboard read\");\n      const r = await run(cmd[0], cmd.slice(1), { timeoutMs: 10_000 });\n      if (r.code !== 0) throw new ExecError(\"clipboard read failed\", r);\n      return { text: r.stdout, encoding: \"utf8\" };\n    },\n    write_clipboard: async ({ text }) => {\n      await probeSession();\n      const cmd = session === \"x11\"\n        ? (tools.xclip ? [\"xclip\", \"-selection\", \"clipboard\"] : [\"xsel\", \"--clipboard\", \"--input\"])\n        : [\"wl-copy\"];\n      need(cmd[0], \"clipboard write\");\n      spawnDetached(cmd[0], cmd.slice(1), String(text ?? \"\"), true);\n      return { written: String(text ?? \"\").length };\n    },\n    cursor_position: async () => {\n      await probeSession();\n      if (session === \"x11\") {\n        const out = await xdotool([\"getmouselocation\"]);\n        const m = /x:(-?\\d+)\\s+y:(-?\\d+)/.exec(out);\n        if (!m) throw new ExecError(`could not parse xdotool getmouselocation output: ${out}`);\n        return { x: Number(m[1]), y: Number(m[2]) };","sourceCodeStart":730,"sourceCodeEnd":766,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/linux.mjs#L730-L766","documentation":"The Linux computer-use backend's read_clipboard handler runs xclip/xsel (X11) or wl-paste (Wayland) to read the system clipboard. If the spawned command exits nonzero within the 10s timeout, the backend throws this ExecError with the process result attached. It indicates the clipboard tool ran but failed to produce clipboard content.","triggerScenarios":"Calling read_clipboard when the X11 clipboard is empty/unowned (xclip exits 1), when xclip/xsel cannot connect to the display, when wl-paste fails under Wayland (no clipboard manager, or no data for the requested mime type), or when the tool crashes.","commonSituations":"Headless/SSH sessions without DISPLAY or WAYLAND_DISPLAY set; running the tool inside a container without access to the compositor; choosing xsel on a desktop where it was never started with a daemon; stale xclip process holding the selection after a clipboard-manager restart.","solutions":["Verify DISPLAY (X11) or WAYLAND_DISPLAY/Wayland socket is set in the environment the backend runs in","Confirm the needed binary is installed and try it manually: `xclip -selection clipboard -o` or `wl-paste`","For Wayland, check the tool supports the clipboard's mime type, or copy something first so the selection is owned","Retry the read; transient selection-ownership races after a clipboard-manager restart are common"],"exampleFix":"// before\nconst text = await readClipboard();\n// after\nlet text;\ntry { text = await readClipboard(); }\ncatch (e) { console.warn('clipboard empty or unavailable:', e.message); text = ''; }","handlingStrategy":"fallback","validationCode":"const bin = isX11 ? (tools.xclip ? 'xclip' : 'xsel') : 'wl-paste';\nconst ok = !!tools[bin === 'xclip' ? 'xclip' : bin] || which(bin);\nif (!ok) throw new SkipError('no clipboard tool available');","typeGuard":null,"tryCatchPattern":"try { text = await readClipboard(); } catch (e) { text = ''; log.warn('clipboard read unavailable', e.message); }","preventionTips":["Check DISPLAY/WAYLAND_DISPLAY before enabling clipboard features","Pre-check tool availability once at backend init","Treat clipboard reads as best-effort and degrade to empty text"],"tags":["clipboard","linux","x11","wayland","process-exit"],"backgroundTag":"command-not-found","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"}