stablyai/orca · error · RuntimeError

{command[0]} failed to set clipboard

Error message

{command[0]} failed to set clipboard

What it means

Raised by write_clipboard (runtime.py:1010) when the xclip or xsel subprocess (used to take clipboard ownership) exits with a non-zero / non-None status after being fed the value on stdin. The check runs after a CLIPBOARD_OWNER_SETTLE_SECONDS sleep; command[0] is the program name (xclip or xsel). wl-copy uses a different code path and does not reach this line.

Source

Thrown at native/computer-use-linux/runtime.py:1010

            timeout=CLIPBOARD_COMMAND_TIMEOUT_SECONDS,
        )
        return
    for command in (["xclip", "-selection", "clipboard"], ["xsel", "--clipboard", "--input"]):
        if not shutil.which(command[0]):
            continue
        process = subprocess.Popen(
            command,
            stdin=subprocess.PIPE,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            text=True,
        )
        if process.stdin is not None:
            process.stdin.write(value)
            process.stdin.close()
        time.sleep(CLIPBOARD_OWNER_SETTLE_SECONDS)
        if process.poll() not in (None, 0):
            raise RuntimeError(f"{command[0]} failed to set clipboard")
        return
    raise RuntimeError("paste_text requires wl-copy, xclip, or xsel")


def set_value(node, value):
    if node is not None and bool(attempt(node.is_editable_text, False)):
        editable = attempt(node.get_editable_text_iface)
        if editable is not None and attempt(lambda: Atspi.EditableText.set_text_contents(editable, str(value)), False):
            return True
    value_iface = attempt(node.get_value_iface) if node is not None else None
    if value_iface is not None:
        return bool(attempt(lambda: Atspi.Value.set_current_value(value_iface, float(value)), False))
    return False


def run_operation(operation):
    tool = operation.get("tool")
    include_screenshot = not bool(operation.get("noScreenshot"))

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Ensure a working X server and DISPLAY (or use wl-copy under a Wayland session with WAYLAND_DISPLAY).
  2. Install wl-copy so write_clipboard takes the wl-copy fast path that does not hit this check.
  3. Diagnose by running `xclip -selection clipboard` manually with a value and checking its exit code and stderr.

Example fix

# before: xclip exits non-zero under headless X
# after (shell): provide a clipboard-capable session or use wl-copy
sudo apt install wl-clipboard  # then run under the matching session
Defensive patterns

Strategy: fallback

Validate before calling

import shutil, os

def clipboard_writer_ok():
    if shutil.which("wl-copy"):
        return True
    tool = "xclip" if shutil.which("xclip") else ("xsel" if shutil.which("xsel") else None)
    if not tool:
        return False
    return bool(os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY"))

Type guard

import shutil, os

def can_write_clipboard() -> bool:
    has_tool = any(shutil.which(t) for t in ("wl-copy", "xclip", "xsel"))
    has_display = bool(os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY"))
    return has_tool and has_display

Try / catch

try:
    run_operation(op)
except RuntimeError as e:
    if "failed to set clipboard" in str(e):
        # fall back to type_text instead of paste
        op = {"tool": "type_text", "text": text}
        run_operation(op)
    else:
        raise

Prevention

When it happens

Trigger: paste_text or write_clipboard is invoked; wl-copy is absent; xclip/xsel is present and started, but exits non-zero — e.g. no X server/clipboard daemon reachable, DISPLAY unset, xsel lost the selection race, or the tool printed an error to its suppressed stderr.

Common situations: Running under SSH/headless without a real X server (DISPLAY points at nothing); a broken X selection daemon; xclip present but the X connection died mid-run; stale xclip binary that crashes.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/ab7bed00388cd7a4. Report an issue: GitHub.