{"record":{"id":"49d6639321fd84e8","repo":"libnyanpasu/clash-nyanpasu","slug":"proxy-selection-succeeded-connection-interruption","errorCode":null,"errorMessage":"proxy selection succeeded; connection interruption error: {:?}; cache refresh error: {:?}","messagePattern":"proxy selection succeeded; connection interruption error: (.+?); cache refresh error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"backend/tauri/src/core/proxies.rs","lineNumber":182,"sourceCode":"        actor: &ActorRef<Message>,\n        group: String,\n        name: String,\n        interrupt: bool,\n    ) -> Result<()> {\n        self.clear();\n        let api = self.core.api_client().await?;\n        api.select_proxy(&group.into(), &name.into()).await?;\n        let interruption = if interrupt {\n            api.close_all_connections()\n                .await\n                .map_err(anyhow::Error::from)\n        } else {\n            Ok(())\n        };\n        let refresh = self.refresh(actor, api).await;\n        match (interruption, refresh) {\n            (Ok(()), Ok(_)) => Ok(()),\n            (interrupt, refresh) => anyhow::bail!(\n                \"proxy selection succeeded; connection interruption error: {:?}; cache refresh error: {:?}\",\n                interrupt.err(),\n                refresh.err()\n            ),\n        }\n    }\n}\n\nimpl Actor for ProxiesActor {\n    type Msg = Message;\n    type State = State;\n    type Arguments = Args;\n    async fn pre_start(\n        &self,\n        _: ActorRef<Message>,\n        args: Args,\n    ) -> Result<State, ActorProcessingErr> {\n        Ok(State {","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/proxies.rs#L164-L200","documentation":"Thrown by the proxies `select` method after the proxy selection itself succeeded, when one or both of the follow-up side effects fail: interrupting existing connections and refreshing the proxy cache/delay snapshot. Since selection was already applied, the error reports both follow-up errors together instead of implying the selection failed. It is a partial-success condition: the group's selected proxy is changed, but post-selection cleanup may not have happened.","triggerScenarios":"Calling `ProxiesClient::select` (via `select` on the proxies service) where `select_proxy` on the core API succeeded, but the `interruption` step (closing active connections) and/or the `refresh` step (cache refresh via actor + API) returned `Err`.","commonSituations":"The mihomo/clash external controller API briefly dropped connections mid-operation; the proxy actor was busy or timed out during refresh; network blips cause connection-interruption calls to fail; the core is restarting while selection is applied.","solutions":["Treat selection as applied: call `get`/refresh again to verify the current proxy snapshot rather than blindly re-selecting.","Retry only the refresh step (e.g. call the refresh/read operation) to repopulate the cache; do not replay the selection mutation automatically.","Check the external controller (core API) connectivity and core health if refresh keeps failing; restart the core if its API is unresponsive."],"exampleFix":"// before: assuming total failure and re-selecting\nclient.select_proxy(group, name).await?; // may re-fire side effects\n\n// after: selection succeeded; verify state and refresh only\nif let Err(e) = client.select_proxy(group, name).await {\n    if e.to_string().contains(\"proxy selection succeeded\") {\n        // refresh snapshot; do not replay the mutation\n        client.get_proxies().await?;\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Probe core API reachability before selecting to reduce follow-up failures\nlet snapshot = client.get_proxies().await?;\nanyhow::ensure!(!snapshot.api.is_revoked(), \"core API unavailable; fix core before selecting\");","typeGuard":null,"tryCatchPattern":"match client.select_proxy(group, name).await {\n    Err(e) if e.to_string().contains(\"proxy selection succeeded\") => {\n        // selection applied; refresh/verify instead of re-selecting\n        let _ = client.get_proxies().await?;\n    }\n    other => other?,\n}","preventionTips":["Verify the core external controller is healthy before proxy operations","Surface partial-success errors to the UI as warnings, not hard failures","Refresh the proxies snapshot after any selection to confirm applied state","Avoid selecting while the core is restarting or provider updates are in flight"],"tags":["proxy","network","partial-failure","side-effects"],"backgroundTag":"api-error-response","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}