libnyanpasu/clash-nyanpasu · error · ClientError

legacy verge bridge is not managed

Error message

legacy verge bridge is not managed

What it means

Raised by `LegacyVergeBridge::managed()` when the bridge's optional `managed` field (`Option<...>`) is `None`, i.e. the bridge was constructed without being attached to a managed legacy verge store/client. Any operation that needs the managed inner (snapshot, get/patch verge config, run mutations) will fail with this error.

Source

Thrown at backend/tauri/src/bridge/verge.rs:356

    fn legacy_mutation_partial(error: anyhow::Error, source: Option<ClientError>) -> ClientError {
        let message = format!(
            "legacy mutation may have non-reversible side effects and requires reconciliation: {error:#}"
        );
        if let Some(ClientError::PartialCommit(partial)) = source {
            return partial.with_legacy_state_uncertain(message).into();
        }

        let primary = ClientError::Anyhow(error);
        PartialCommit::new(&primary, Vec::new(), Vec::new(), Vec::new())
            .with_legacy_state_uncertain(message)
            .into()
    }

    fn managed(&self) -> ClientResult<&LegacyVergeBridgeInner> {
        self.managed
            .as_deref()
            .ok_or_else(|| anyhow::anyhow!("legacy verge bridge is not managed").into())
    }

    async fn get_verge_config_unlocked(&self) -> ClientResult<IVerge> {
        let managed = self.managed()?;
        let app = managed.client.get_app_config().await?;
        let session = managed.client.get_session_state().await?;
        let clash = managed.client.get_clash_config().await?;

        Ok(super::legacy_iverge_from_typed(
            self.legacy_store.snapshot()?,
            &app,
            &session,
            &clash,
        )?)
    }

    async fn refresh_legacy_projection(&self) -> ClientResult<IVerge> {
        let managed = self.managed()?;

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Ensure the app bootstrap/composition root constructs and attaches the managed inner before any command uses the bridge.
  2. Check initialization order: complete actor spawn and bridge setup before registering/serving Tauri commands.
  3. In tests, construct the bridge with a managed inner (test fixtures with injected fake clients) instead of the bare constructor.
  4. Add an early readiness check so commands return a clear 'not initialized' state rather than hitting this error.

Example fix

// before: bridge used before setup
let bridge = LegacyVergeBridge::new();
bridge.get_verge_config().await?; // panics-free error: not managed

// after: setup first, then use
let bridge = LegacyVergeBridge::new();
bridge.attach_managed(client, legacy_verge_path).await?; // populate managed
bridge.get_verge_config().await?;
Defensive patterns

Strategy: type-guard

Validate before calling

// guard before using the bridge
if !bridge.is_managed() {
    return Err(ClientError::from(anyhow::anyhow!(
        "verge bridge not initialized; complete bootstrap first"
    )));
}

Type guard

fn is_managed(bridge: &LegacyVergeBridge) -> bool {
    bridge.managed_handle().is_some()
}

Try / catch

match bridge.get_verge_config().await {
    Err(e) if e.to_string().contains("not managed") => {
        // bootstrap not finished; retry after initialization signal
        bootstrap_ready.notified().await;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Invoking any bridge operation (`patch_verge_config`, `get_verge_config`, `run_legacy_verge_mutation`, `replace_verge_config`) on a `LegacyVergeBridge` that was built without calling the setup that populates `self.managed` (e.g. used before bootstrap/`AppSupervisor` wired it, or in a context where the legacy bridge was intentionally disabled).

Common situations: Calling Tauri commands during app startup before the composition root has initialized the bridge; unit tests instantiating the bridge without a managed inner; a refactor making `managed` optional without guarding all call sites.

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


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