libnyanpasu/clash-nyanpasu · error
listen() called before prepare()
Error message
listen() called before prepare()
What it means
The plugin's listen() spawns a thread that builds a Unix socket path from the OnceCell ID set by prepare(). If listen() is called before prepare(), ID.get() is None and the .expect panics. Like register(), it enforces that prepare() initializes the plugin before listening for deep-link events.
Source
Thrown at backend/tauri-plugin-deep-link/src/linux.rs:107
.file_name()
.ok_or_else(|| Error::new(
ErrorKind::NotFound,
"Couldn't get file name of current executable.",
))?
.to_string_lossy()
));
remove_file(&target)?;
target.pop();
Ok(())
}
pub fn listen<F: FnMut(String) + Send + 'static>(mut handler: F) -> Result<()> {
std::thread::spawn(move || {
let addr = format!(
"/tmp/{}-deep-link.sock",
ID.get().expect("listen() called before prepare()")
);
let listener = UnixListener::bind(addr).expect("Can't create listener");
for stream in listener.incoming() {
match stream {
Ok(mut stream) => {
let mut buffer = String::new();
if let Err(io_err) = stream.read_to_string(&mut buffer) {
log::error!("Error reading incoming connection: {}", io_err.to_string());
};
handler(dbg!(buffer));
}
Err(err) => {
log::error!("Incoming connection failed: {}", err);
continue;
}View on GitHub (pinned to f7dbce2997)
Solutions
- Ensure prepare() runs before listen(); wire the plugin through the standard Tauri builder.
- If listen() is reached via register(), fix the ordering at the register() call site (see error 247).
- Defer listen() until after plugin initialization completes (e.g. in the app's setup callback).
- Add an early assertion/log in your bootstrap that prepare() has run before spawning listeners.
Example fix
// before
listen(|url| handle(url));
deep_link::prepare("com.example.app");
// after
deep_link::prepare("com.example.app");
listen(|url| handle(url)); Defensive patterns
Strategy: validation
Validate before calling
// Ensure initialization order
if !deep_link::is_prepared() { deep_link::prepare(APP_ID); }
deep_link::listen(handler)?; Try / catch
catch_unwind around listen(); on panic log "prepare() must run before listen()" and re-init.
Prevention
- Initialize prepare() before any listen()/register() call.
- Wire the plugin via the Tauri builder rather than manual calls.
- Start listeners in the setup hook, after plugin init.
- Fix ordering at register() call sites (register calls listen indirectly).
When it happens
Trigger: Calling deep_link listen() (directly or indirectly through register(), which calls it) before prepare() populated ID.
Common situations: Startup-order mistakes in manual plugin wiring; tests that invoke listen() standalone; custom launchers that start listening before the plugin's prepare hook executes.
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
- Called register() before prepare()
- Can't create listener
- Local socket too many crashes
- data directory not found.
- Couldn't get file name of curent executable.
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/7170fc20457b5a5f.
Report an issue: GitHub.