Hmbown/CodeWhale · warning · anyhow::Error

Clipboard unavailable: {err}

Error message

Clipboard unavailable: {err}

What it means

Thrown by ClipboardHandler::write_text when the detected terminal context forces ClipboardWriteOrder::TerminalClientOnly (an SSH session with no forwarded X11/Wayland display, or CODEWHALE_SSH_CLIPBOARD=terminal). On this path no native clipboard helper is tried; the write goes straight to enqueue_terminal_write (tmux load-buffer or OSC 52), and any failure there is wrapped as 'Clipboard unavailable: {err}'. Typical inner errors: selection larger than OSC52_MAX_BYTES (100 KiB) outside tmux, stdout not a terminal, terminal writer spawn/queue failure, or tmux errors.

Source

Thrown at crates/tui/src/tui/clipboard.rs:435

    pub fn write_text(&mut self, text: &str) -> Result<()> {
        #[cfg(test)]
        {
            if let Some(writer) = self.terminal_writer.as_ref() {
                return writer.enqueue(text, self.terminal_context.in_tmux);
            }
            if self.fail_text_writes {
                bail!("test clipboard unavailable");
            }
            self.written_text.push(text.to_string());
            Ok(())
        }

        #[cfg(not(test))]
        {
            if self.terminal_context.write_order() == ClipboardWriteOrder::TerminalClientOnly {
                return self
                    .enqueue_terminal_write(text)
                    .map_err(|err| anyhow::anyhow!("Clipboard unavailable: {err}"));
            }

            #[cfg(all(target_os = "linux", not(target_env = "ohos")))]
            if write_text_with_wlcopy(text).is_ok() {
                return Ok(());
            }

            #[cfg(any(
                target_os = "macos",
                target_os = "windows",
                all(target_os = "linux", not(target_env = "ohos"))
            ))]
            {
                self.ensure_clipboard();
                if let Some(clipboard) = self.clipboard.as_mut()
                    && clipboard.set_text(text.to_string()).is_ok()
                {
                    return Ok(());

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Copy a smaller selection (under 100 KiB), or run inside tmux where the OSC 52 size cap does not apply
  2. Use an OSC 52-capable terminal (iTerm2, kitty, WezTerm, Alacritty; tmux needs set-clipboard on) and keep stdout attached to the TTY
  3. Forward a display (ssh -X/-Y) or set CODEWHALE_SSH_CLIPBOARD=graphical with a live display so the native clipboard path is used instead
  4. Wait for the queued terminal write to drain before copying again; avoid back-to-back large copies

Example fix

# before
ssh remote-host        # no -X; copy a 500 KiB selection
# -> Clipboard unavailable: selection is too large for OSC 52 clipboard fallback

# after
ssh -X remote-host     # forwarded display -> native clipboard path
# or run inside tmux on the remote host and keep selections under 100 KiB
Defensive patterns

Strategy: fallback

Validate before calling

// Rust - pre-flight the terminal-client copy path
use std::io::IsTerminal;
const OSC52_MAX_BYTES: usize = 100 * 1024;

fn terminal_copy_ok(text: &str, in_tmux: bool) -> bool {
    if !in_tmux {
        if text.len() > OSC52_MAX_BYTES { return false; }
        if !std::io::stdout().is_terminal() { return false; }
    }
    true
}

Try / catch

match clipboard.write_text(text) {
    Ok(()) => show_copy_receipt(),
    Err(err) => show_warning(format!("Clipboard unavailable: {err:#}")),
} // copy is best-effort: never abort the turn on clipboard failure

Prevention

When it happens

Trigger: write_text() while SSH_CLIENT/SSH_CONNECTION/SSH_TTY is set with no usable DISPLAY/WAYLAND_DISPLAY, and then: (a) not in tmux and text.len() > 100*1024, (b) io::stdout() is not a terminal (piped/redirected), (c) the TerminalClipboardWriter thread failed to spawn or stopped, (d) another terminal write still occupies the single-slot queue ('another terminal clipboard write is still queued'), or (e) inside tmux the `tmux load-buffer -w -` child fails to spawn or exits non-zero.

Common situations: SSH into a remote host without X11 forwarding and copying a large transcript; TUI stdout piped or redirected; local terminal with OSC 52 disabled or unsupported (many defaults); rapid consecutive large copies overrunning the one-slot write queue.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/e7cf80c47c61b80b. Report an issue: GitHub.