{"record":{"id":"321a5f3dd88295e7","repo":"astrid-runtime/astrid","slug":"admin-request-timed-out-after-waiting-for-wa","errorCode":null,"errorMessage":"Admin request timed out after {:?} waiting for {want_response}","messagePattern":"Admin request timed out after (.+?) waiting for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-uplink/src/admin_client.rs","lineNumber":181,"sourceCode":"\n    async fn send_and_wait(\n        &mut self,\n        topic: Topic,\n        want_response: Topic,\n        request_id: String,\n        payload: Value,\n    ) -> Result<AdminResponseBody> {\n        let msg = IpcMessage::new(topic, IpcPayload::RawJson(payload), Uuid::nil())\n            .with_principal(self.caller.to_string());\n        self.inner.send_message(msg).await?;\n\n        let deadline = tokio::time::Instant::now()\n            .checked_add(self.timeout)\n            .unwrap_or_else(tokio::time::Instant::now);\n        loop {\n            let remaining = deadline.saturating_duration_since(tokio::time::Instant::now());\n            if remaining.is_zero() {\n                anyhow::bail!(\n                    \"Admin request timed out after {:?} waiting for {want_response}\",\n                    self.timeout\n                );\n            }\n            let read = tokio::time::timeout(remaining, self.inner.read_raw_frame()).await;\n            let frame = match read {\n                Ok(Ok(Some(bytes))) => bytes,\n                Ok(Ok(None)) => {\n                    anyhow::bail!(\"Daemon closed the connection before responding\");\n                },\n                Ok(Err(e)) => return Err(e),\n                Err(_) => {\n                    anyhow::bail!(\n                        \"Admin request timed out after {:?} waiting for {want_response}\",\n                        self.timeout\n                    );\n                },\n            };","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-uplink/src/admin_client.rs#L163-L199","documentation":"send_and_wait sends an admin request to the daemon and loops reading frames until a wanted response arrives, with a self.timeout deadline computed up front. If the whole budget is consumed before the matching response frame is seen, it bails naming the expected response type. This distinguishes 'daemon alive but slow/unresponsive' from connection errors.","triggerScenarios":"Calling AdminClient::request or request_agent_derive when the daemon takes longer than self.timeout to produce the wanted response — e.g. daemon busy with a long operation, response never sent, or timeout configured too small for the operation.","commonSituations":"Daemon under heavy load (large sync/derive operations) exceeding the client timeout; a daemon bug drops the reply for that request type; client constructed with a very short timeout for an inherently slow admin operation.","solutions":["Increase the AdminClient timeout to comfortably exceed the daemon's worst-case handling time for the operation.","Check the daemon's logs/health to confirm it is processing admin requests and not wedged; restart it if hung.","Retry the request with backoff once the daemon is responsive again — the request may not have been processed.","Verify the daemon version supports the requested operation (an unsupported request may silently get no reply)."],"exampleFix":"// before\nclassic let client = AdminClient::with_timeout(Duration::from_secs(5));\n// after\nlet client = AdminClient::with_timeout(Duration::from_secs(60));","handlingStrategy":"retry","validationCode":"// Pre-check daemon responsiveness with a cheap call before expensive requests\nadmin_client.request(HealthCheck {}).await?; // fails fast if daemon unresponsive","typeGuard":null,"tryCatchPattern":"match admin_client.request(req).await {\n    Ok(resp) => resp,\n    Err(e) if e.to_string().contains(\"Admin request timed out\") => {\n        tokio::time::sleep(Duration::from_secs(2)).await;\n        admin_client.request(req).await? // bounded retry\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Configure the AdminClient timeout above the daemon's worst-case operation latency.","Health-check the daemon before long admin operations.","Watch daemon load and queue depth; back off when it is saturated.","Verify the daemon version supports every request type you send."],"tags":["timeout","ipc","admin","daemon"],"backgroundTag":"request-timeout","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}