libnyanpasu/clash-nyanpasu · error
URL event received before prepare() was called
Error message
URL event received before prepare() was called
What it means
In debug builds on macOS, the secondary-instance handler reads the identifier from the ID OnceCell to build the /tmp/<id>-deep-link.sock path. If prepare() was never called, ID.get() returns None and this expect() panics. It enforces that prepare() precedes any URL event handling.
Source
Thrown at backend/tauri-plugin-deep-link/src/macos.rs:88
let mut cb = HANDLER.get().unwrap().lock().unwrap();
cb(s);
}
}
);
impl Handler {
pub fn new() -> Retained<Self> {
let cls = Self::class();
unsafe { msg_send_id![msg_send_id![cls, alloc], init] }
}
}
#[cfg(debug_assertions)]
fn secondary_handler(s: String) {
let addr = format!(
"/tmp/{}-deep-link.sock",
ID.get()
.expect("URL event received before prepare() was called")
);
if let Ok(mut stream) = UnixStream::connect(addr) {
if let Err(io_err) = stream.write_all(s.as_bytes()) {
log::error!(
"Error sending message to primary instance: {}",
io_err.to_string()
);
};
}
std::process::exit(0);
}
pub fn listen<F: FnMut(String) + Send + 'static>(handler: F) -> Result<()> {
#[cfg(debug_assertions)]
let addr = format!(
"/tmp/{}-deep-link.sock",
ID.get().expect("listen() called before prepare()")
);View on GitHub (pinned to f7dbce2997)
Solutions
- Call prepare(identifier) before register()/listen() in the app setup
- Ensure every code path that can handle a URL runs prepare() first
- If the identifier is dynamic, prepare() it before spawning any secondary-instance handler
Example fix
// before
register("myapp");
// after
prepare("com.example.myapp");
register("myapp"); Defensive patterns
Strategy: validation
Validate before calling
assert!(ID.get().is_some(), "call prepare() before handling deep links");
Type guard
fn is_prepared() -> bool { ID.get().is_some() } Prevention
- Always call prepare() before register()/listen()
- Keep prepare() at the top of your deep-link init helper
- Cover the startup path with a smoke test
When it happens
Trigger: A secondary instance receives a URL event (secondary_handler fires) before the app code called prepare(identifier); calling listen()/register() without prepare() first so no identifier was stored.
Common situations: Forgetting prepare() in a custom plugin setup; registering deep-link handling conditionally so prepare() is skipped on some code path while listen() still runs; macOS dev builds where single-instance handoff fires early.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- listen() called before prepare()
- prepare() called more than once with different identifiers.
- prepare() called more than once with different identifiers.
- Can't create listener
- register() called before prepare()
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/f21300167e452ac6.
Report an issue: GitHub.