libnyanpasu/clash-nyanpasu · critical
NyanpasuClient is not available for verge patch
Error message
NyanpasuClient is not available for verge patch
What it means
patch_verge_entrypoint is a migration bridge: it tries to fetch the managed NyanpasuClient from the Tauri app state and delegate the verge config patch to it. If the condition that guards the try_state lookup fails (client not yet registered in app state), it bails with "NyanpasuClient is not available for verge patch" — meaning dependency injection of the app facade hasn't happened.
Source
Thrown at backend/tauri/src/feat.rs:130
/// typed actors are reseeded after a legacy side-effect write. Falls back to a direct
/// `patch_verge` with the managed `NyanpasuClient` during early startup when the bridge
/// is not yet managed.
async fn patch_verge_entrypoint(patch: IVerge) -> Result<()> {
// TODO(actor-migration): compatibility bridge for legacy feature toggles.
// Reason: feature paths still enter through Handle::global() and legacy Config::verge().
// Remove when: feature toggles call typed actor clients through injected command adapters.
let app_handle = handle::Handle::global().app_handle.lock().clone();
if let Some(app_handle) = app_handle {
if let Some(legacy) = app_handle.try_state::<crate::bridge::verge::LegacyVergeBridge>() {
let legacy = legacy.inner().clone();
legacy.patch_verge_config(patch).await?;
return Ok(());
}
if let Some(client) = app_handle.try_state::<crate::client::NyanpasuClient>() {
return patch_verge(client.inner().clone(), patch).await;
}
}
bail!("NyanpasuClient is not available for verge patch")
}
// 切换系统代理
pub fn toggle_system_proxy() {
let enable = Config::verge().draft().enable_system_proxy;
let enable = enable.unwrap_or(false);
tauri::async_runtime::spawn(async move {
match patch_verge_entrypoint(IVerge {
enable_system_proxy: Some(!enable),
..IVerge::default()
})
.await
{
Ok(_) => handle::Handle::refresh_verge(),
Err(err) => log::error!(target: "app", "{err:?}"),
}
});View on GitHub (pinned to f7dbce2997)
Solutions
- Ensure NyanpasuClient is managed via app.manage(NyanpasuClient) in the bootstrap/setup before any UI, tray, or hotkey handlers can run.
- Delay tray/hotkey registration until after the client is injected into state.
- In tests, construct and manage a NyanpasuClient (or call patch_verge directly with a client instance) instead of relying on app_handle state.
Example fix
// before
if let Some(client) = app_handle.try_state::<crate::client::NyanpasuClient>() {
return patch_verge(client.inner().clone(), patch).await;
}
bail!("NyanpasuClient is not available for verge patch")
// after
// in setup, before registering tray/hotkeys:
let client = NyanpasuClient::new(deps).await?;
app.manage(client);
// then patch_verge_entrypoint will find the client Defensive patterns
Strategy: try-catch
Validate before calling
// before triggering any verge toggle, confirm the client is managed:
let ready = app_handle.try_state::<crate::client::NyanpasuClient>().is_some();
if !ready { eprintln!("app bootstrap not finished yet"); return; } Try / catch
match patch_verge_entrypoint(app_handle, patch).await {
Err(e) if e.to_string().contains("NyanpasuClient is not available") => {
// retry after bootstrap or queue the patch until setup completes
},
other => other?,
} Prevention
- Manage NyanpasuClient in tauri setup() before registering tray, hotkeys, or IPC commands.
- Disable tray/hotkey actions until a "bootstrap ready" flag is set.
- In tests, inject a real NyanpasuClient rather than relying on app state.
When it happens
Trigger: Calling toggle_system_proxy / enable_system_proxy / disable_system_proxy / toggle_tun_mode / enable_tun_mode / disable_tun_mode before NyanpasuClient is inserted into Tauri managed state (e.g. during early startup, before bootstrap completes, or after a failed bootstrap).
Common situations: Hotkey/tray actions firing during app initialization before setup() manages the client; a panic or error earlier in bootstrap that skipped state management; calling these feat functions from tests without a Tauri app handle with managed state.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- tray not found
- update_systray unhandled error
- app_handle is not exist
- app handle is none
- legacy mutation failed: {error:#}
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/578e2c7b91fa0090.
Report an issue: GitHub.