{"record":{"id":"e4f13d678c3c6784","repo":"astrid-runtime/astrid","slug":"mcp-broker-did-not-become-ready-for-principal-pr","errorCode":null,"errorMessage":"MCP broker did not become ready for principal '{principal}' within {}s; no capsule answered {TOOLS_LIST_TOPIC}","messagePattern":"MCP broker did not become ready for principal '(.+?)' within (.+?)s; no capsule answered (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/mcp/readiness.rs","lineNumber":101,"sourceCode":"    io: &mut I,\n    principal: &PrincipalId,\n    ready_deadline: Duration,\n    retry_interval: Duration,\n) -> Result<()> {\n    let deadline = Instant::now()\n        .checked_add(ready_deadline)\n        .unwrap_or_else(Instant::now);\n    let mut outstanding = HashSet::new();\n\n    send_probe(io, principal, &mut outstanding).await?;\n    let mut retry_at = Instant::now()\n        .checked_add(retry_interval)\n        .unwrap_or(deadline);\n\n    loop {\n        let now = Instant::now();\n        if now >= deadline {\n            anyhow::bail!(\n                \"MCP broker did not become ready for principal '{principal}' within {}s; no capsule answered {TOOLS_LIST_TOPIC}\",\n                ready_deadline.as_secs()\n            );\n        }\n        if now >= retry_at {\n            debug!(%principal, \"MCP broker readiness probe interval elapsed; retrying idempotent tools/list\");\n            send_probe(io, principal, &mut outstanding).await?;\n            retry_at = Instant::now()\n                .checked_add(retry_interval)\n                .unwrap_or(deadline);\n            continue;\n        }\n\n        let wake_at = retry_at.min(deadline);\n        let frame = match tokio::time::timeout_at(wake_at, io.read_raw_frame()).await {\n            Ok(Ok(Some(frame))) => frame,\n            Ok(Ok(None)) => {\n                anyhow::bail!(","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/mcp/readiness.rs#L83-L119","documentation":"wait_for_broker_on polls an MCP broker by sending idempotent tools/list requests over the daemon connection until a capsule answers or the ready deadline expires. When the deadline elapses without any capsule responding to TOOLS_LIST_TOPIC, it fails with this error naming the principal and the configured timeout.","triggerScenarios":"Calling `astrid mcp ready` (via wait_for_broker) or internal readiness probes when no capsule serving the principal's tools/list responds before ready_deadline (as_secs()) elapses.","commonSituations":"No capsules/agents loaded for that principal at daemon cold start; capsule crashed or is still loading; wrong principal supplied so its capsule set is empty; daemon reachable but broker subsystem wedged; timeout set too short for slow capsule loading.","solutions":["Increase the readiness timeout (larger ready deadline) and retry.","Verify the principal has capsules registered that serve tools/list (`astrid agent`/capsule listing) and use the correct principal.","Check daemon logs for capsule load failures and restart the daemon/capsules.","Retry after cold start completes — tests show a replayed probe succeeds once the principal's capsules load.","Confirm TOOLS_LIST_TOPIC is supported by the installed capsule versions (version mismatch)."],"exampleFix":"// before\nastrid mcp ready --principal alice --timeout 5   # capsules still loading\n// after\nastrid mcp ready --principal alice --timeout 60","handlingStrategy":"retry","validationCode":"let deadline = Duration::from_secs(cfg.ready_timeout_secs);\nassert!(deadline >= Duration::from_secs(10), \"ready timeout too small for capsule cold start\");\n// also confirm the principal has capsules before probing\n","typeGuard":null,"tryCatchPattern":"match wait_for_broker(&mut io, principal, timeout).await {\n    Err(e) if e.to_string().contains(\"did not become ready\") => {\n        // extend deadline / verify capsules loaded / retry probe once\n    }\n    other => other?,\n}","preventionTips":["Set a readiness timeout large enough for capsule cold-start loading","Ensure the principal actually has capsules registered before probing","Monitor daemon logs for capsule load failures","Retry the probe after cold start — a replayed probe typically succeeds"],"tags":["timeout","mcp","broker","readiness"],"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"}