libnyanpasu/clash-nyanpasu · critical
Invalid identifier
Error message
Invalid identifier
What it means
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.
Source
Thrown at backend/tauri-plugin-deep-link/src/windows.rs:140
}
Err(e) => {
log::error!("Error accepting connection: {e}");
}
}
}
CRASH_COUNT.fetch_add(1, Ordering::Release);
let _ = listen(handler);
});
});
Ok(())
}
#[inline(never)]
pub fn prepare(identifier: &str) {
let name: Name = identifier
.to_ns_name::<GenericNamespaced>()
.expect("Invalid identifier");
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("failed to create tokio runtime")
.block_on(async move {
for _ in 0..3 {
match LocalSocketStream::connect(name.clone()).await {
Ok(conn) => {
// We are the secondary instance.
// Prep to activate primary instance by allowing another process to take focus.
// A workaround to allow AllowSetForegroundWindow to succeed - press a key.
// This was originally used by Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=837796
// dummy_keypress();
// let primary_instance_pid = conn.peer_pid().unwrap_or(ASFW_ANY);
// unsafe {View on GitHub (pinned to f7dbce2997)
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.
Example fix
// before
deep_link::prepare(&config.custom_id); // custom_id may be empty/invalid
// after
let name = interprocess::local_socket::GenericNamespaced::to_ns_name(&config.custom_id)
.expect("app identifier must be a valid namespaced name");
deep_link::prepare(config.custom_id.as_str()); Defensive patterns
Strategy: validation
Validate before calling
use interprocess::local_socket::{GenericNamespaced, ToNsName};
pub fn is_valid_identifier(id: &str) -> bool {
!id.is_empty()
&& id.len() <= 100
&& id.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '-' | '_'))
&& id.to_ns_name::<GenericNamespaced>().is_ok()
} Try / catch
// Rust panics, not catchable like exceptions; validate before calling
assert!(is_valid_identifier(APP_IDENTIFIER), "invalid deep-link identifier: {APP_IDENTIFIER}");
deep_link::prepare(APP_IDENTIFIER); Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- URL not provided
- Local socket too many crashes
- semaphore should never closed
- version overflow
- prepare() called more than once with different identifiers.
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/96a39111d86df592.
Report an issue: GitHub.