{"record":{"id":"6a4cfe831c404b9d","repo":"libnyanpasu/clash-nyanpasu","slug":"handler-was-already-set","errorCode":null,"errorMessage":"Handler was already set","messagePattern":"Handler was already set","errorType":"exception","errorClass":"std::io::Error (AlreadyExists)","httpStatus":null,"severity":"error","filePath":"backend/tauri-plugin-deep-link/src/macos.rs","lineNumber":122,"sourceCode":"        \"/tmp/{}-deep-link.sock\",\n        ID.get().expect(\"listen() called before prepare()\")\n    );\n\n    #[cfg(debug_assertions)]\n    if HANDLER\n        .set(match UnixStream::connect(&addr) {\n            Ok(_) => Mutex::new(Box::new(secondary_handler)),\n            Err(err) => {\n                log::error!(\"Error creating socket listener: {}\", err.to_string());\n                if err.kind() == ErrorKind::ConnectionRefused {\n                    let _ = remove_file(&addr);\n                }\n                Mutex::new(Box::new(handler))\n            }\n        })\n        .is_err()\n    {\n        return Err(std::io::Error::new(\n            ErrorKind::AlreadyExists,\n            \"Handler was already set\",\n        ));\n    }\n\n    #[cfg(not(debug_assertions))]\n    if HANDLER.set(Mutex::new(Box::new(handler))).is_err() {\n        return Err(std::io::Error::new(\n            ErrorKind::AlreadyExists,\n            \"Handler was already set\",\n        ));\n    }\n\n    unsafe {\n        let event_manager: Retained<AnyObject> =\n            msg_send_id![class!(NSAppleEventManager), sharedAppleEventManager];\n\n        let handler = Handler::new();","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri-plugin-deep-link/src/macos.rs#L104-L140","documentation":"On macOS the deep-link plugin stores the global event handler in a `OnceLock`-like `HANDLER` static. `listen` tries to install the handler with a debug-only and a release-mode set; the first (cfg(debug_assertions)) attempt fails if a handler was already registered, producing this `AlreadyExists` io::Error. It means the app is trying to register a second deep-link listener.","triggerScenarios":"Calling `register`/`listen` twice in a debug build — e.g. registering in both the tauri setup hook and a window event, or on app re-init — while HANDLER already holds a handler.","commonSituations":"Double registration during development hot-reload, calling listen from multiple windows, or plugin setup code executed more than once.","solutions":["Register the deep-link handler exactly once, in the tauri `setup` hook.","Guard the call with a Once/flag or check whether a handler is already installed before calling listen.","Ignore ErrorKind::AlreadyExists if a second registration attempt is harmless in your flow."],"exampleFix":"// before\napp.listen(\"myapp\", |event| { ... }); // also called elsewhere\n// after\nstatic LISTENER: Once = Once::new();\nLISTENER.call_once(|| { app.listen(\"myapp\", |event| { ... }); });","handlingStrategy":"try-catch","validationCode":"// static guard\nstatic REGISTERED: AtomicBool = AtomicBool::new(false);\nif REGISTERED.swap(true, Ordering::SeqCst) { return; } // already registered","typeGuard":null,"tryCatchPattern":"match register(app) {\n    Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {}, // handler already installed\n    other => other?,\n}","preventionTips":["Call listen/register only once, from the tauri setup hook","Use a Once guard around registration","Don't re-register on window recreation or hot reload"],"tags":["macos","deep-link","lifecycle","double-registration"],"backgroundTag":"invalid-state-transition","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}