libnyanpasu/clash-nyanpasu · error
register() called before prepare()
Error message
register() called before prepare()
What it means
register() on Windows writes a registry key whose display value is 'URL:<identifier>', reading the identifier from the ID OnceCell. If prepare() was not called first, ID.get() is None and this expect() panics. prepare() must precede register().
Source
Thrown at backend/tauri-plugin-deep-link/src/windows.rs:45
pub fn register<F: FnMut(String) + Send + 'static>(schemes: &[&str], handler: F) -> Result<()> {
listen(handler)?;
for scheme in schemes {
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
let base = Path::new("Software").join("Classes").join(scheme);
let exe = tauri_utils::platform::current_exe()?
.display()
.to_string()
.replace("\\\\?\\", "");
let (key, _) = hkcu.create_subkey(&base)?;
key.set_value(
"",
&format!(
"URL:{}",
ID.get().expect("register() called before prepare()")
),
)?;
key.set_value("URL Protocol", &"")?;
let (icon, _) = hkcu.create_subkey(base.join("DefaultIcon"))?;
icon.set_value("", &format!("\"{}\",0", exe))?;
let (cmd, _) = hkcu.create_subkey(base.join("shell").join("open").join("command"))?;
cmd.set_value("", &format!("\"{}\" \"%1\"", exe))?;
}
Ok(())
}
pub fn unregister(schemes: &[&str]) -> Result<()> {
for scheme in schemes {
let hkcu = RegKey::predef(HKEY_CURRENT_USER);View on GitHub (pinned to f7dbce2997)
Solutions
- Call prepare(identifier) before register()
- Move both calls into one setup function so ordering is enforced
- In tests, prepare() in a common setup step before register()
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 register()");
Type guard
fn is_prepared() -> bool { ID.get().is_some() } Prevention
- Call prepare() before any registry/scheme registration
- Group prepare()+register() in one init function
- Keep registration out of installer-time code that skips prepare()
When it happens
Trigger: Calling register() before prepare(); registering the URL scheme during installer/init code that runs before the plugin's prepare(); conditional setup that skips prepare().
Common situations: Custom scheme registration invoked early in app bootstrap; refactors that moved register() before prepare(); tests calling register() standalone.
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.
- 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/cf8ba4655bb4a1d9.
Report an issue: GitHub.