{"record":{"id":"47647b4efede918b","repo":"libnyanpasu/clash-nyanpasu","slug":"url-not-provided","errorCode":null,"errorMessage":"URL not provided","messagePattern":"URL not provided","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri-plugin-deep-link/src/windows.rs","lineNumber":166,"sourceCode":"                match LocalSocketStream::connect(name.clone()).await {\n                    Ok(conn) => {\n                        // We are the secondary instance.\n                        // Prep to activate primary instance by allowing another process to take focus.\n\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);","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri-plugin-deep-link/src/windows.rs#L148-L184","documentation":"When the process connects to an existing primary instance's local socket, it becomes the secondary instance and must forward the deep-link URL. The library assumes the URL was passed as the first CLI argument (`std::env::args().nth(1)`) and panics with 'URL not provided' if it is absent. This is an environment/launch-contract violation: the second launch of the app did not carry the deep-link URL as argv[1].","triggerScenarios":"A second instance launched via the deep-link scheme handler without the URL as the first command-line argument — e.g. the OS/browser launched `app.exe` with no extra argument, the protocol registration template is wrong, or the process was started manually or by a test harness with no args.","commonSituations":"Incorrect Windows registry protocol command template (missing `\"%1\"`); launching the exe manually from a terminal while another instance is running; a custom launcher/updater restarting the binary without forwarding arguments; IDE run configurations that don't pass arguments.","solutions":["Fix the deep-link/protocol registration so the URL is appended as the first argument, e.g. `\"C:\\path\\app.exe\" \"%1\"` in the Windows registry command for the URL scheme.","If launching programmatically, pass the deep-link URL as the first argument: `Command::new(exe).arg(url)`.","When testing manually with a primary instance already running, invoke `app.exe myapp://some/path` instead of `app.exe` with no arguments."],"exampleFix":"// before (registry command)\n\"C:\\\\apps\\\\myapp.exe\"\n// after\n\"C:\\\\apps\\\\myapp.exe\" \"%1\"","handlingStrategy":"validation","validationCode":"// Check before assuming secondary-instance handoff; guard on argv length\nfn first_cli_arg() -> Option<String> {\n    std::env::args().nth(1)\n}","typeGuard":null,"tryCatchPattern":"// The plugin panics; prevent by ensuring launcher contract, or patch prepare call site\nmatch std::env::args().nth(1) {\n    Some(url) if url.contains(\"://\") => deep_link::prepare(APP_IDENTIFIER),\n    _ => eprintln!(\"no deep-link URL argument; skipping single-instance handoff\"),\n}","preventionTips":["Register the URL-scheme handler with the URL argument placeholder (\"%1\" on Windows) and verify after install/upgrade.","Never launch the app binary manually without arguments while another instance is running.","In launchers/updaters, always forward the original argv to restarted processes.","Add an integration test that spawns a second instance with a deep-link URL argument."],"tags":["rust","cli-arguments","deep-link","panic","windows"],"backgroundTag":"missing-required-argument","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"}