{"record":{"id":"0c78f1f4b8e2defc","repo":"libnyanpasu/clash-nyanpasu","slug":"write-config-timed-out-after-timeout","errorCode":null,"errorMessage":"write config timed out after {timeout:?}","messagePattern":"write config timed out after (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/nyanpasu-core/src/state/manager/persistent_builder.rs","lineNumber":220,"sourceCode":"                formatter.serialize(&mut buf, &builder_for_save, config_prefix.as_deref())?;\n                let file = AtomicFile::new(&config_path, AllowOverwrite);\n                tokio::task::spawn_blocking(move || file.write(|f| f.write_all(&buf)))\n                    .await?\n                    .with_context(|| format!(\"failed to write config: {config_path}\"))?;\n                Ok::<_, anyhow::Error>(())\n            })\n            .await;\n\n        match result {\n            Ok(((), report)) => {\n                self.current_builder = builder;\n                Ok(report)\n            }\n            Err(e) => match e {\n                WithEffectError::State(e) => Err(UpsertError::State(e)),\n                WithEffectError::Effect(e) => Err(UpsertError::WriteConfig(e)),\n                WithEffectError::EffectTimedOut(timeout) => Err(UpsertError::WriteConfig(\n                    anyhow::anyhow!(\"write config timed out after {timeout:?}\"),\n                )),\n            },\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::state::{Ack, StateAckSubscriber, StateChange, SubscriberName};\n    use serde::{Deserialize, Serialize};\n    use std::sync::{\n        Arc,\n        atomic::{AtomicUsize, Ordering},\n    };\n    use tempfile::tempdir;\n    use tokio::fs;\n","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/nyanpasu-core/src/state/manager/persistent_builder.rs#L202-L238","documentation":"State::upsert maps WithEffectError::EffectTimedOut to UpsertError::WriteConfig with this message: the coordinated 'write config' effect did not finish within the given timeout, so the operation is reported as failed (state side already committed or rolled back per coordinator policy).","triggerScenarios":"Calling upsert on the persistent state manager while the inner effect (runtime config write / patch via coordinator) exceeds the timeout — slow disk, blocked core, or deadlock in the effect path.","commonSituations":"Heavy config rebuilds, core restart taking longer than the timeout, or system under load causing the effect future to stall.","solutions":["Increase the timeout passed to the effect call if the write is legitimately slow.","Investigate why the effect is slow (core responsiveness, disk I/O, cross-actor round-trips).","Retry the upsert — check whether state was committed despite the timeout and reconcile if needed.","Avoid synchronous cross-actor cycles in the effect path that can deadlock until timeout."],"exampleFix":"// before\nlet report = manager.upsert(patch).await?;\n// after\nmatch manager.upsert(patch).await {\n    Ok(report) => Ok(report),\n    Err(UpsertError::WriteConfig(e)) if e.to_string().contains(\"timed out\") => {\n        log::warn!(\"config write timed out; retrying once: {e}\");\n        manager.upsert(patch).await.map_err(Into::into)\n    }\n    Err(e) => Err(e.into()),\n}","handlingStrategy":"retry","validationCode":"// verify dependencies respond before a timed upsert\nif tokio::time::timeout(Duration::from_secs(2), core_client.ping()).await.is_err() {\n    eprintln!(\"core unresponsive; upsert likely to time out\");\n}","typeGuard":null,"tryCatchPattern":"match manager.upsert(patch).await {\n    Err(UpsertError::WriteConfig(e)) if e.to_string().contains(\"timed out\") => {\n        tokio::time::sleep(Duration::from_secs(1)).await;\n        manager.upsert(patch).await // retry; verify state consistency after\n    }\n    other => other,\n}","preventionTips":["Set timeouts generously enough for slow disks and core restarts","Avoid cross-actor synchronous cycles that stall effect execution","After a timeout, check whether the config was actually written before retrying","Monitor core responsiveness and degrade early instead of blocking"],"tags":["timeout","state","config","async"],"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"}