libnyanpasu/clash-nyanpasu · error
Failed to flush socket
Error message
Failed to flush socket
What it means
The deep-link plugin's Windows single-instance handler panics when flushing the data written to the inter-process socket fails. flush() forces buffered bytes out to the OS socket; an error means the connection to the already-running instance broke mid-handshake (closed, reset, or unreachable). The library uses .expect(), so the failure aborts the new process instead of being recoverable.
Source
Thrown at backend/tauri-plugin-deep-link/src/windows.rs:175
// 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.");
}
}
std::process::exit(0);
}
Err(e) => {View on GitHub (pinned to f7dbce2997)
Solutions
- Ensure the primary instance's server/listener stays alive and accepts connections before the secondary writes to the socket
- Replace the .expect on flush with graceful error handling so a transient connection failure exits quietly instead of panicking
- Retry the connection once after a short delay before giving up
- Check that no firewall/AV is blocking local inter-process socket connections
Example fix
// before
socket_tx.flush().await.expect("Failed to flush socket");
// after
if let Err(e) = socket_tx.flush().await {
eprintln!("Failed to flush single-instance socket: {e}");
std::process::exit(0);
} Defensive patterns
Strategy: try-catch
Try / catch
if let Err(e) = socket_tx.flush().await {
eprintln!("single-instance flush failed: {e}");
// app already running took over — exit quietly
std::process::exit(0);
} Prevention
- Handle flush/write errors instead of expect so secondary instances exit gracefully
- Keep the primary instance's socket listener alive until full shutdown
- Log the underlying io error to distinguish reset vs refused connections
When it happens
Trigger: A second instance launches, connects to the first instance's named-pipe/TCP socket, writes the deep-link URL, and socket_tx.flush().await fails because the primary instance's listener dropped the connection, exited, or the socket was reset between write and flush.
Common situations: Primary app quitting just as a second instance starts; antivirus or firewall interfering with the local socket; socket path/permission problems on Windows; a stale or crashed primary instance whose socket is half-open.
Related errors
- Local socket too many crashes
- Invalid identifier
- URL not provided
- Failed to write to socket
- prepare() called more than once with different identifiers.
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/028a4013b4739fa1.
Report an issue: GitHub.