{"record":{"id":"249c84da6eec77b2","repo":"libnyanpasu/clash-nyanpasu","slug":"failed-to-write-to-socket","errorCode":null,"errorMessage":"Failed to write to socket","messagePattern":"Failed to write to socket","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri-plugin-deep-link/src/windows.rs","lineNumber":170,"sourceCode":"\n                        // A workaround to allow AllowSetForegroundWindow to succeed - press a key.\n                        // This was originally used by Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=837796\n                        // dummy_keypress();\n\n                        // let primary_instance_pid = conn.peer_pid().unwrap_or(ASFW_ANY);\n                        // unsafe {\n                        //     let success = AllowSetForegroundWindow(primary_instance_pid) != 0;\n                        //     if !success {\n                        //         log::warn!(\"AllowSetForegroundWindow failed.\");\n                        //     }\n                        // }\n                        let (socket_rx, mut socket_tx) = conn.split();\n                        let mut socket_rx = socket_rx.as_tokio_async_read();\n                        let url = std::env::args().nth(1).expect(\"URL not provided\");\n                        socket_tx\n                            .write_all(url.as_bytes())\n                            .await\n                            .expect(\"Failed to write to socket\");\n                        socket_tx\n                            .write_all(b\"\\n\")\n                            .await\n                            .expect(\"Failed to write to socket\");\n                        socket_tx.flush().await.expect(\"Failed to flush socket\");\n\n                        let mut reader = BufReader::new(&mut socket_rx);\n                        let mut buf = String::new();\n                        if let Err(e) = reader.read_line(&mut buf).await {\n                            eprintln!(\"Error reading from connection: {e}\");\n                        }\n                        buf.pop();\n                        dummy_keypress();\n                        let pid = buf.parse::<u32>().unwrap_or(ASFW_ANY);\n                        unsafe {\n                            let success = AllowSetForegroundWindow(pid) != 0;\n                            if !success {\n                                eprintln!(\"AllowSetForegroundWindow failed.\");","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri-plugin-deep-link/src/windows.rs#L152-L188","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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).","solutions":["Relaunch the application: the handoff usually succeeds once a healthy primary instance is listening.","Investigate why the primary instance died or closed the connection during accept (check primary logs for panics in the deep-link listener).","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.","As a hardening step, wrap the URL handoff in a retry that falls back to starting normally as the primary if the socket dies."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Library panics on write failure; guard by probing the connection state at the call site\n// and treating panic-free handoff as best-effort:\nlet result = std::panic::catch_unwind(|| deep_link::prepare(APP_IDENTIFIER));\nif result.is_err() {\n    eprintln!(\"deep-link handoff to primary failed; continuing\");\n}","preventionTips":["Keep the primary instance's accept/read loop panic-free and always reading the full line before processing.","Log primary-instance lifecycle so handoff failures can be correlated with primary shutdown.","Emit a UI/OS notification when the primary exits so users understand a second launch may fail to focus it.","If forking the plugin, replace expect() on writes with graceful fallback to becoming the primary."],"tags":["rust","ipc","socket-write","broken-pipe","windows"],"backgroundTag":"broken-pipe","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}