{"record":{"id":"2661199600e616e1","repo":"Hmbown/CodeWhale","slug":"primary-selection-busy-or-unavailable","errorCode":null,"errorMessage":"PRIMARY selection busy or unavailable","messagePattern":"PRIMARY selection busy or unavailable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/tui/clipboard/primary.rs","lineNumber":61,"sourceCode":"                                        .clipboard(LinuxClipboardKind::Primary)\n                                        .text()\n                                        .ok()\n                                })\n                                .filter(|text| {\n                                    !text.is_empty() && text.len() <= super::PRIMARY_MAX_BYTES\n                                });\n                            let _ = reply.try_send(text);\n                        }\n                    }\n                }\n            })?;\n        Ok(Self { sender })\n    }\n\n    pub(super) fn write(&self, text: &str) -> Result<()> {\n        self.sender\n            .try_send(Request::Write(text.to_string()))\n            .map_err(|_| anyhow!(\"PRIMARY selection busy or unavailable\"))\n    }\n\n    pub(super) fn read(&self) -> Option<String> {\n        let (sender, receiver) = mpsc::sync_channel(1);\n        self.sender.try_send(Request::Read(sender)).ok()?;\n        // A late reply is discarded, never inserted into a subsequently edited\n        // composer. Clipboard failure stays quiet and cannot submit a command.\n        receiver\n            .recv_timeout(Duration::from_millis(250))\n            .ok()\n            .flatten()\n    }\n}\n","sourceCodeStart":43,"sourceCodeEnd":75,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/tui/clipboard/primary.rs#L43-L75","documentation":"`PrimarySelection::write` hands a Write request to a dedicated clipboard thread over a bounded (capacity 1) sync_channel, because X11/Wayland display I/O must not run on the TUI thread. `try_send` returns `Err` when the channel is full (the single slot is still occupied by a previous request the display-server thread has not drained) or when the receiver thread is gone (channel disconnected), and that is mapped to this single \"PRIMARY selection busy or unavailable\" error. It is intentionally non-blocking: a stalled or crashed display-backed clipboard worker degrades PRIMARY-selection support instead of freezing the UI.","triggerScenarios":"Calling `write` while a previously enqueued write has not yet been consumed by the worker thread (channel of capacity 1 already full — e.g. rapid successive writes or the display server stalling in arboard's `set().clipboard(LinuxClipboardKind::Primary)`), or after the worker thread has exited (thread spawn failed or panicked), so the receiver is dropped.","commonSituations":"Selecting text rapidly in a compositor/X11 session where the clipboard provider (e.g. a clipman/clipboard manager) grabs the selection and makes each arboard call slow, so writes queue faster than they drain; headless or SSH sessions without a display server where `Clipboard::new()` fails and the thread churns without a clipboard; Wayland compositors without a PRIMARY-selection protocol implementation.","solutions":["Retry the write after a short delay — the previous request usually drains once the display server becomes responsive; the single-slot buffer means one backoff is typically enough.","Treat the error as non-fatal: PRIMARY selection is an auxiliary transport, so fall back to the normal clipboard path (`set()` on the default clipboard / OSC 52) instead of failing the user action.","Verify a display server with PRIMARY selection support is reachable (DISPLAY/WAYLAND_DISPLAY set, or a Wayland compositor implementing primary-selection); otherwise skip PRIMARY handling.","If it reproduces persistently, check for a panicked 'primary-selection' thread (thread spawn or arboard panic) and restart the selection worker."],"exampleFix":"// before\nprimary.write(text).map_err(|e| e).context(\"copy to selection\")?;\n// after\nif let Err(err) = primary.write(text) {\n    tracing::debug!(\"primary selection unavailable: {err}; using default clipboard\");\n    clipboard.write(text)?; // fallback transport\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = primary.write(text) {\n    log::debug!(\"primary selection busy: {e}\");\n    std::thread::sleep(std::time::Duration::from_millis(50));\n    primary.write(text).or_else(|_| default_clipboard.write(text))?;\n}","preventionTips":["Rate-limit PRIMARY writes so the single-slot channel is not overrun.","Never treat PRIMARY-selection failure as fatal; it is auxiliary to the main clipboard.","Ensure a display server with PRIMARY support exists before enabling the selection worker.","Log at debug level so repeated busy drops are visible without surfacing errors to users."],"tags":["clipboard","linux","x11","wayland","channel-full"],"backgroundTag":"resource-busy","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T21:17:16.096Z"}