{"record":{"id":"fe4a8410c2727ebf","repo":"libnyanpasu/clash-nyanpasu","slug":"prepare-called-more-than-once-with-different-ide","errorCode":null,"errorMessage":"prepare() called more than once with different identifiers.","messagePattern":"prepare\\(\\) called more than once with different identifiers\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri-plugin-deep-link/src/linux.rs","lineNumber":156,"sourceCode":"            if let Err(io_err) =\n                stream.write_all(std::env::args().nth(1).unwrap_or_default().as_bytes())\n            {\n                log::error!(\n                    \"Error sending message to primary instance: {}\",\n                    io_err.to_string()\n                );\n            };\n            std::process::exit(0);\n        }\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        }\n    };\n    ID.set(identifier.to_string())\n        .expect(\"prepare() called more than once with different identifiers.\");\n}\n","sourceCodeStart":138,"sourceCodeEnd":158,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri-plugin-deep-link/src/linux.rs#L138-L158","documentation":"prepare() stores the deep-link plugin identifier in a OnceCell that can only be set once. If prepare() is called a second time with a different identifier than the first call, ID.set() returns Err and this expect() panics. The library uses this to guarantee a single, consistent per-app identifier for IPC socket paths.","triggerScenarios":"Calling prepare(identifier) twice in one process with different identifier strings, e.g. during app re-initialization, hot-reload of the Tauri setup hook, or two test cases reusing one process with different bundle IDs.","commonSituations":"Dev hot-reload rebuilding the Tauri app state without restarting the process; test harnesses calling prepare() per test with a distinct identifier; accidentally invoking prepare() in both a plugin init hook and the app setup closure.","solutions":["Call prepare() exactly once per process, early in the app entry point","Use the same identifier string on every call (derive it from a single constant/config)","If re-initialization is required, run it in a fresh process instead of calling prepare() again","Guard with Once: use a wrapper that only forwards the first prepare() call"],"exampleFix":"// before\nprepare(\"com.app.dev\");\n// ...\nprepare(\"com.app.test\"); // panics\n// after\nconst IDENTIFIER: &str = \"com.app.dev\";\nprepare(IDENTIFIER); // called once, from one place","handlingStrategy":"validation","validationCode":"if ID.get().map(|id| id.as_str()) == Some(identifier) { return; } // skip duplicate prepare with same id\nassert!(ID.get().is_none(), \"prepare() already called\");","typeGuard":"fn is_prepared() -> bool { ID.get().is_some() }","tryCatchPattern":null,"preventionTips":["Call prepare() once, in a single bootstrap location","Derive the identifier from one shared constant","Avoid re-running app setup in the same process"],"tags":["rust","initialization","panic","deep-link"],"backgroundTag":"internal-invariant-violation","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"}