libnyanpasu/clash-nyanpasu · error

Failed to write to socket

Error message

Failed to write to socket

What it means

The secondary instance writes the URL bytes to the connected local socket and `.expect()`s that the async write succeeds. A panic here means the socket write to the primary instance failed mid-connection — the primary died or closed the connection between accept and read, or the pipe/socket was reset. The library treats failure to hand off the URL as fatal for the secondary instance.

Source

Thrown at backend/tauri-plugin-deep-link/src/windows.rs:170

                        // A workaround to allow AllowSetForegroundWindow to succeed - press a key.
                        // This was originally used by Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=837796
                        // dummy_keypress();

                        // let primary_instance_pid = conn.peer_pid().unwrap_or(ASFW_ANY);
                        // unsafe {
                        //     let success = AllowSetForegroundWindow(primary_instance_pid) != 0;
                        //     if !success {
                        //         log::warn!("AllowSetForegroundWindow failed.");
                        //     }
                        // }
                        let (socket_rx, mut socket_tx) = conn.split();
                        let mut socket_rx = socket_rx.as_tokio_async_read();
                        let url = std::env::args().nth(1).expect("URL not provided");
                        socket_tx
                            .write_all(url.as_bytes())
                            .await
                            .expect("Failed to write to socket");
                        socket_tx
                            .write_all(b"\n")
                            .await
                            .expect("Failed to write to socket");
                        socket_tx.flush().await.expect("Failed to flush socket");

                        let mut reader = BufReader::new(&mut socket_rx);
                        let mut buf = String::new();
                        if let Err(e) = reader.read_line(&mut buf).await {
                            eprintln!("Error reading from connection: {e}");
                        }
                        buf.pop();
                        dummy_keypress();
                        let pid = buf.parse::<u32>().unwrap_or(ASFW_ANY);
                        unsafe {
                            let success = AllowSetForegroundWindow(pid) != 0;
                            if !success {
                                eprintln!("AllowSetForegroundWindow failed.");

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Relaunch the application: the handoff usually succeeds once a healthy primary instance is listening.
  2. Investigate why the primary instance died or closed the connection during accept (check primary logs for panics in the deep-link listener).
  3. Make the primary's accept/read loop robust: never panic between accept and read_line, and keep the listener thread alive per the plugin's reconnect logic.
  4. As a hardening step, wrap the URL handoff in a retry that falls back to starting normally as the primary if the socket dies.
Defensive patterns

Strategy: retry

Try / catch

// Library panics on write failure; guard by probing the connection state at the call site
// and treating panic-free handoff as best-effort:
let result = std::panic::catch_unwind(|| deep_link::prepare(APP_IDENTIFIER));
if result.is_err() {
    eprintln!("deep-link handoff to primary failed; continuing");
}

Prevention

When it happens

Trigger: `socket_tx.write_all(url.as_bytes()).await` returns Err after `LocalSocketStream::connect` succeeded: the primary instance exited or crashed just after accepting, the primary's listener thread panicked before reading, or the OS closed the local socket handle.

Common situations: Primary instance is shutting down (user closed it) at the exact moment a second launch hands off the URL; primary crashed inside its accept loop; primary hung and was killed by a watchdog; Windows named-pipe broken due to primary process termination (broken pipe / ERROR_BROKEN_PIPE).

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/249c84da6eec77b2. Report an issue: GitHub.