libnyanpasu/clash-nyanpasu · error
Called register() before prepare()
Error message
Called register() before prepare()
What it means
On Linux, the deep-link plugin's register() writes a .desktop template that reads the app ID from a OnceCell (ID) populated by prepare(). Calling register() before prepare() leaves ID empty, and ID.get().expect(...) panics. This enforces the plugin's required initialization order: prepare() must run first.
Source
Thrown at backend/tauri-plugin-deep-link/src/linux.rs:50
target.push(&file_name);
let mime_types = format!(
"{};",
schemes
.iter()
.map(|s| format!("x-scheme-handler/{}", s))
.collect::<Vec<String>>()
.join(";")
);
let mut file = File::create(&target)?;
file.write_all(
format!(
include_str!("template.desktop"),
name = ID
.get()
.expect("Called register() before prepare()")
.split('.')
.last()
.unwrap(),
exec = std::env::var("APPIMAGE").unwrap_or_else(|_| exe.display().to_string()),
mime_types = mime_types
)
.as_bytes(),
)?;
// update-desktop-database [-q|--quiet] [-v|--verbose] [DIRECTORY...]
target.pop();
Command::new("update-desktop-database")
.arg(&target)
.status()?;
for scheme in schemes {
Command::new("xdg-mime")View on GitHub (pinned to f7dbce2997)
Solutions
- Call prepare() (or set the ID via the plugin's prepare hook) before any register() call.
- Ensure the plugin is added through the Tauri builder so its setup/prepare hook runs at startup.
- Move manual register() calls into code that runs after plugin initialization completes.
- If you cannot reorder, gate register() behind a check that the ID is initialized and report a clear error instead.
Example fix
// before
register_all(); // calls register()
deep_link::prepare("com.example.app");
// after
deep_link::prepare("com.example.app");
register_all(); // register() now finds ID initialized Defensive patterns
Strategy: validation
Validate before calling
// Call before register()
fn deep_link_ready() -> bool { /* ID OnceCell populated */ deep_link::is_prepared() } Try / catch
match std::panic::catch_unwind(|| deep_link::register()) { Err(_) => eprintln!("call prepare() before register()"), ... } Prevention
- Always run prepare() before register().
- Register the plugin through the standard Tauri builder so prepare runs automatically.
- Keep manual deep-link setup in the app setup callback, after plugin init.
- Add a startup assertion that prepare() completed.
When it happens
Trigger: Invoking the plugin's register() (desktop-file registration) before calling prepare() in the same process, e.g. registering deep links during early setup before the plugin's prepare hook ran.
Common situations: Custom startup code that registers deep-link handlers manually before the Tauri plugin builder's prepare step; refactors that move plugin setup out of the standard builder chain; AppImage packaging scripts calling register too 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()
- 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/8fe1539de4d33d98.
Report an issue: GitHub.