libnyanpasu/clash-nyanpasu · error
URL not provided
Error message
URL not provided
What it means
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].
Source
Thrown at backend/tauri-plugin-deep-link/src/windows.rs:166
match LocalSocketStream::connect(name.clone()).await {
Ok(conn) => {
// We are the secondary instance.
// Prep to activate primary instance by allowing another process to take focus.
// 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);View on GitHub (pinned to f7dbce2997)
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.
Example fix
// before (registry command) "C:\\apps\\myapp.exe" // after "C:\\apps\\myapp.exe" "%1"
Defensive patterns
Strategy: validation
Validate before calling
// Check before assuming secondary-instance handoff; guard on argv length
fn first_cli_arg() -> Option<String> {
std::env::args().nth(1)
} Try / catch
// The plugin panics; prevent by ensuring launcher contract, or patch prepare call site
match std::env::args().nth(1) {
Some(url) if url.contains("://") => deep_link::prepare(APP_IDENTIFIER),
_ => eprintln!("no deep-link URL argument; skipping single-instance handoff"),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Local socket too many crashes
- prepare() called more than once with different identifiers.
- URL event received before prepare() was called
- listen() called before prepare()
- prepare() called more than once with different identifiers.
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/47647b4efede918b.
Report an issue: GitHub.