libnyanpasu/clash-nyanpasu · error

app handle is none

Error message

app handle is none

What it means

Hotkey::register looks up the stored Tauri AppHandle to access global_shortcut manager; if it is None it bails with 'app handle is none'. This means hotkey registration was attempted before the Tauri app handle was stored in the Hotkey struct (or after teardown). It's a lifecycle invariant violation inside the hotkey service.

Source

Thrown at backend/tauri/src/core/hotkey.rs:254

        // Validate super key requirement
        if !Self::validate_super_key(hotkey) {
            bail!("{}", t!("hotkey_error.missing_super_key"));
        }
        Ok(())
    }

    /// Check if the hotkey contains a super key modifier (case-insensitive)
    pub fn validate_super_key(hotkey: &str) -> bool {
        let hotkey_lower = hotkey.to_lowercase();
        SUPER_KEYS
            .iter()
            .any(|key| hotkey_lower.contains(&key.to_lowercase()))
    }

    fn register(&self, hotkey: &str, func: &str) -> Result<()> {
        let app_handle = self.app_handle.lock();
        if app_handle.is_none() {
            bail!("app handle is none");
        }
        let manager = app_handle.as_ref().unwrap().global_shortcut();

        if manager.is_registered(hotkey) {
            manager.unregister(hotkey)?;
        }

        let hotkey_func: HotkeyFunc = func.trim().parse()?;

        manager.on_shortcut(hotkey, move |app_handle, hotkey, ev| {
            if let ShortcutState::Pressed = ev.state {
                tracing::info!("hotkey pressed: {}", hotkey);
                hotkey_func.execute(app_handle);
            }
        })?;

        log::info!(target: "app", "register hotkey {hotkey} {func}");
        Ok(())

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Ensure update()/register() is only called after the app handle is injected (post-setup initialization order)
  2. Queue pending registrations and flush them once the handle becomes available
  3. Migrate per actor-migration: own registration in a HotkeyActor whose startup arguments include the shortcut adapter, removing the None case
  4. Improve the error message to mention hotkey registration before app initialization

Example fix

// before
let app_handle = self.app_handle.lock();
if app_handle.is_none() {
    bail!("app handle is none");
}
// after
let Some(app_handle) = self.app_handle.lock().as_ref() else {
    log::warn!("hotkey registration skipped: app handle not ready");
    return Ok(());
};
Defensive patterns

Strategy: try-catch

Validate before calling

fn hotkeys_ready(h: &Hotkey) -> bool {
    h.app_handle.lock().is_some()
}

Try / catch

if let Err(e) = hotkey.update() {
    log::warn!("hotkey registration deferred: {e}");
    pending_registration.store(true, Ordering::Relaxed);
}

Prevention

When it happens

Trigger: update() re-registering all hotkeys before app setup completes or after the handle was cleared; enabling hotkeys in config applied during early startup before the handle exists.

Common situations: Config with enable_hotkey loaded before Tauri setup finished; tests constructing Hotkey without an app handle; restart/teardown races.

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


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/ca938964ebbfa866. Report an issue: GitHub.