{"record":{"id":"2a5ee771a8192b06","repo":"libnyanpasu/clash-nyanpasu","slug":"clash-stream-actor-timed-out","errorCode":null,"errorMessage":"Clash stream actor timed out","messagePattern":"Clash stream actor timed out","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/core/clash/ws.rs","lineNumber":695,"sourceCode":"        Ok(Self(Arc::new(Inner {\n            actor,\n            connections,\n            events,\n        })))\n    }\n    async fn call<T: Send + 'static>(\n        &self,\n        message: impl FnOnce(RpcReplyPort<T>) -> Message,\n    ) -> Result<T> {\n        match self\n            .0\n            .actor\n            .call(message, Some(Duration::from_secs(10)))\n            .await\n            .context(\"Clash stream actor unavailable\")?\n        {\n            CallResult::Success(value) => Ok(value),\n            CallResult::Timeout => anyhow::bail!(\"Clash stream actor timed out\"),\n            CallResult::SenderError => anyhow::bail!(\"Clash stream actor reply dropped\"),\n        }\n    }\n    pub async fn start(&self) -> Result<()> {\n        self.call(Message::Start).await\n    }\n    #[allow(dead_code)]\n    pub async fn stop(&self) -> Result<()> {\n        self.call(Message::Stop).await\n    }\n    pub async fn snapshot(&self) -> Result<ClashWsSnapshot> {\n        self.call(Message::Snapshot).await\n    }\n    pub async fn set_recording(\n        &self,\n        kind: ClashWsKind,\n        enabled: bool,\n    ) -> Result<ClashWsRecording> {","sourceCodeStart":677,"sourceCodeEnd":713,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/clash/ws.rs#L677-L713","documentation":"The Clash websocket/IPC bridge sends a typed message to a ractor actor with a 10-second RPC timeout and maps CallResult::Timeout to this error. It means the Clash stream actor received the request but did not reply within 10 seconds — the actor is busy, blocked, or its handler hung. Distinguish it from 'actor unavailable' (send failure) and 'reply dropped' (sender error).","triggerScenarios":"Calling start() (or other Message variants) on the clash ws client while the actor is stuck processing a prior message, the backend connection is stalled, or the actor task is starved on a blocked await for more than 10 seconds.","commonSituations":"Clash core hanging or slow to accept a websocket connection; network stalls to the core endpoint; actor deadlocked on a synchronous cross-actor call; heavy event loop under load.","solutions":["Check the Clash core process is alive and the websocket endpoint is responsive; restart the core if hung","Increase the 10s timeout only if the operation is legitimately slow — prefer diagnosing the stall first","Inspect the actor's message loop for blocking calls or cross-actor cycles that can deadlock (avoid StateActor -> CoreActor -> StateActor patterns)","Add retry-with-backoff at the caller for idempotent messages like Start"],"exampleFix":"// before\n.actor.call(message, Some(Duration::from_secs(10)))\n// after\nmatch actor.call(message, Some(Duration::from_secs(10))).await {\n    Ok(CallResult::Timeout) => log::warn!(\"clash stream actor timed out; retrying once\"),\n    other => return other.context(\"Clash stream actor unavailable\"),\n}","handlingStrategy":"retry","validationCode":"// before calling: check core is reachable\n// e.g. ping the clash controller endpoint with a short HTTP timeout","typeGuard":null,"tryCatchPattern":"match client.start().await {\n    Err(e) if e.to_string().contains(\"timed out\") => retry_with_backoff(3, || client.start()),\n    other => other,\n}","preventionTips":["Keep the Clash core process healthy and monitored","Avoid blocking calls or cross-actor cycles inside the actor handler","Use the actor's own timeout instead of wrapping in outer cancellation-prone timeouts"],"tags":["timeout","actor","websocket","rust"],"backgroundTag":"request-timeout","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"}