{"record":{"id":"96a39111d86df592","repo":"libnyanpasu/clash-nyanpasu","slug":"invalid-identifier","errorCode":null,"errorMessage":"Invalid identifier","messagePattern":"Invalid identifier","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"backend/tauri-plugin-deep-link/src/windows.rs","lineNumber":140,"sourceCode":"                        }\n                        Err(e) => {\n                            log::error!(\"Error accepting connection: {e}\");\n                        }\n                    }\n                }\n                CRASH_COUNT.fetch_add(1, Ordering::Release);\n                let _ = listen(handler);\n            });\n    });\n\n    Ok(())\n}\n\n#[inline(never)]\npub fn prepare(identifier: &str) {\n    let name: Name = identifier\n        .to_ns_name::<GenericNamespaced>()\n        .expect(\"Invalid identifier\");\n\n    tokio::runtime::Builder::new_current_thread()\n        .enable_all()\n        .build()\n        .expect(\"failed to create tokio runtime\")\n        .block_on(async move {\n            for _ in 0..3 {\n                match LocalSocketStream::connect(name.clone()).await {\n                    Ok(conn) => {\n                        // We are the secondary instance.\n                        // Prep to activate primary instance by allowing another process to take focus.\n\n                        // A workaround to allow AllowSetForegroundWindow to succeed - press a key.\n                        // This was originally used by Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=837796\n                        // dummy_keypress();\n\n                        // let primary_instance_pid = conn.peer_pid().unwrap_or(ASFW_ANY);\n                        // unsafe {","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri-plugin-deep-link/src/windows.rs#L122-L158","documentation":"In `prepare()`, the app identifier string is validated with interprocess-local-socket's `to_ns_name::<GenericNamespaced>()`, which rejects names that are not valid namespaced identifiers (empty, too long, or containing forbidden characters). The library `.expect()`s success because the identifier is a compile-time/app-level constant that is assumed valid. When it is not, the panic 'Invalid identifier' aborts instance startup before any socket work begins.","triggerScenarios":"Calling `deep_link::prepare(identifier)` with an identifier that fails `GenericNamespaced` validation: an empty string, a name exceeding the platform length limit (typically 104 bytes on Unix-like namespace rules), or a name containing characters such as `/`, `\\`, or other non-allowed characters.","commonSituations":"A misconfigured tauri.conf.json `identifier` (e.g. left as the default placeholder, contains uppercase/slashes, or is empty); passing a user-supplied or dynamically built string instead of a fixed app identifier; a refactor that changed the identifier format and broke namespace rules.","solutions":["Fix the application identifier in tauri.conf.json so it is a valid namespaced name: non-empty, reasonably short, lowercase alphanumeric with dots or dashes (e.g. com.example.app).","Validate the identifier before calling prepare(): `identifier.to_ns_name::<GenericNamespaced>()` in a Result context, or check length and character set yourself.","Ensure prepare() receives the same fixed identifier used at primary-instance setup (`listen`), not a trimmed, URL-decoded, or user-malleable variant."],"exampleFix":"// before\ndeep_link::prepare(&config.custom_id); // custom_id may be empty/invalid\n// after\nlet name = interprocess::local_socket::GenericNamespaced::to_ns_name(&config.custom_id)\n    .expect(\"app identifier must be a valid namespaced name\");\ndeep_link::prepare(config.custom_id.as_str());","handlingStrategy":"validation","validationCode":"use interprocess::local_socket::{GenericNamespaced, ToNsName};\npub fn is_valid_identifier(id: &str) -> bool {\n    !id.is_empty()\n        && id.len() <= 100\n        && id.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '-' | '_'))\n        && id.to_ns_name::<GenericNamespaced>().is_ok()\n}","typeGuard":null,"tryCatchPattern":"// Rust panics, not catchable like exceptions; validate before calling\nassert!(is_valid_identifier(APP_IDENTIFIER), \"invalid deep-link identifier: {APP_IDENTIFIER}\");\ndeep_link::prepare(APP_IDENTIFIER);","preventionTips":["Keep the identifier a compile-time constant derived from tauri.conf.json and validate it in a unit test.","Never build the identifier dynamically from user input or URL components.","Add a startup test calling to_ns_name::<GenericNamespaced>() on the app identifier."],"tags":["rust","single-instance","panic","identifier-validation","windows"],"backgroundTag":"invalid-identifier-format","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"}