libnyanpasu/clash-nyanpasu · warning
app_handle is not exist
Error message
app_handle is not exist
What it means
Handle::emit sends a serialized event to the Tauri frontend via the stored global AppHandle. If the AppHandle was never set (app not initialized) it bails with 'app_handle is not exist'. This is a lifecycle/ordering error: events are being emitted before the Tauri application handle is registered in the global singleton.
Source
Thrown at backend/tauri/src/core/handle.rs:100
// Tray::update_systray(app_handle.as_ref().unwrap())?;
Handle::emit("update_systray", ())?;
Ok(())
}
/// update the system tray state
pub fn update_systray_part() -> Result<()> {
let app_handle = Self::global().app_handle.lock();
if app_handle.is_none() {
bail!("update_systray unhandled error");
}
Tray::update_part(app_handle.as_ref().unwrap())?;
Ok(())
}
pub fn emit<S: Serialize + Clone>(event: &str, payload: S) -> Result<()> {
let app_handle = Self::global().app_handle.lock();
if app_handle.is_none() {
bail!("app_handle is not exist");
}
app_handle.as_ref().unwrap().emit(event, payload)?;
Ok(())
}
}
View on GitHub (pinned to f7dbce2997)
Solutions
- Delay event-producing tasks until after Tauri setup stores the app handle
- Make emit fail-soft: log a warning and return Ok when no handle is registered, since UI events are non-critical
- Replace Handle::global() with an injected UiEventSink adapter so the dependency is explicit and testable
- Use a OnceLock/watch channel so emitters wait for handle availability instead of failing
Example fix
// before
bail!("app_handle is not exist");
// after
let Some(app_handle) = app_handle.as_ref() else {
log::debug!("emit skipped, app_handle not ready: {event}");
return Ok(());
}; Defensive patterns
Strategy: try-catch
Validate before calling
fn events_ready(handle: &Handle) -> bool {
handle.app_handle.lock().is_some()
} Try / catch
if let Err(e) = Handle::emit("config-changed", payload) {
log::debug!("event emit skipped: {e}");
} Prevention
- Start event-producing tasks after app initialization
- Make UI events non-fatal
- Inject a UiEventSink instead of using the global Handle
When it happens
Trigger: Calling Handle::emit(event, payload) during early startup before setup() stores the app handle; background tasks (log watchers, core callbacks) firing events at startup or teardown after handle removal.
Common situations: Config/log listeners started before Tauri setup completes; tests exercising event-emitting code without a Tauri runtime; shutdown races where a task emits after the app dropped.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- update_systray unhandled error
- app handle is none
- NyanpasuClient is not available for verge patch
- Shutdown hook already set
- Failed to get module handle: {err}
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/261c0b63e9db8ec1.
Report an issue: GitHub.