{"record":{"id":"0a5694079964ce25","repo":"astrid-runtime/astrid","slug":"candidate-generation-for-id-did-not-signal-rea","errorCode":null,"errorMessage":"candidate generation for '{id}' did not signal ready within {}ms","messagePattern":"candidate generation for '(.+?)' did not signal ready within (.+?)ms","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/lib.rs","lineNumber":4717,"sourceCode":"#[cfg(not(all(target_arch = \"wasm32\", target_os = \"unknown\")))]\nasync fn activate_and_wait_ready(\n    id: &astrid_capsule_types::CapsuleId,\n    candidate: &mut dyn astrid_capsule::capsule::Capsule,\n) -> Result<(), anyhow::Error> {\n    use astrid_capsule::capsule::ReadyStatus;\n\n    let activation_timeout = std::time::Duration::from_secs(30);\n    let readiness_timeout = std::time::Duration::from_millis(500);\n    match astrid_runtime::time::timeout(activation_timeout, candidate.activate()).await {\n        Ok(result) => result?,\n        Err(_) => anyhow::bail!(\n            \"candidate generation for '{id}' did not activate within {}ms\",\n            activation_timeout.as_millis()\n        ),\n    }\n    match candidate.wait_ready(readiness_timeout).await {\n        ReadyStatus::Ready => Ok(()),\n        ReadyStatus::Timeout => anyhow::bail!(\n            \"candidate generation for '{id}' did not signal ready within {}ms\",\n            readiness_timeout.as_millis()\n        ),\n        ReadyStatus::Crashed => {\n            anyhow::bail!(\"candidate generation for '{id}' exited before signaling ready\")\n        },\n    }\n}\n\n/// Attempts to restart a failed capsule, respecting backoff and max retries.\n///\n/// Records ONE restart attempt (advancing backoff and the retry count) per call\n/// when eligible. The count is a measure of CONSECUTIVE health failures: a busy\n/// capsule whose restart legitimately leaves a lingering old instance is NOT\n/// treated as a failure here — the tracker is pruned by the health monitor the\n/// moment the capsule RECOVERS (see the retain in [`spawn_capsule_health_monitor`]),\n/// so only a capsule that keeps failing across ticks accumulates toward the cap.\n/// This deliberately does not key off the [`RestartOutcome`], which is diagnostic","sourceCodeStart":4699,"sourceCodeEnd":4735,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/lib.rs#L4699-L4735","documentation":"After a candidate generation activates successfully, the kernel waits `readiness_timeout` (500ms) via `candidate.wait_ready()` for the capsule to signal Ready. If the status returns `ReadyStatus::Timeout`, the kernel throws this error: the capsule is running but never reported readiness in time.","triggerScenarios":"`candidate.wait_ready(readiness_timeout)` returns `ReadyStatus::Timeout` — the capsule activated but its ready signal (e.g. health/ready handshake) was not observed within 500ms.","commonSituations":"Capsule's ready-signaling logic is delayed by slow init (cache warm-up, first request latency); readiness probe interval longer than the 500ms window; a bug where the capsule never calls the ready signal; flapping processes that activate but stall before signaling.","solutions":["Verify the capsule actually emits its Ready signal after activation and that nothing blocks before it.","Increase `readiness_timeout` (currently 500ms) if the capsule legitimately needs longer to become ready.","Check for slow initialization inside the capsule (warm-up work that should be deferred post-ready).","Confirm the ready channel/IPC between capsule and kernel is functioning (no dropped signals)."],"exampleFix":"// before\nlet readiness_timeout = std::time::Duration::from_millis(500);\n// after\nlet readiness_timeout = std::time::Duration::from_millis(5000); // allow slow readiness probes","handlingStrategy":"retry","validationCode":"// Pre-flight: ensure the capsule's ready-signal path is wired before activation\n// assert candidate exposes a readiness channel and that init work is deferred past ready","typeGuard":null,"tryCatchPattern":"match candidate.wait_ready(readiness_timeout).await {\n    ReadyStatus::Ready => Ok(()),\n    ReadyStatus::Timeout => { log::warn!(\"ready signal timeout\"); /* backoff-retry */ }\n    ReadyStatus::Crashed => { /* handle crash */ }\n}","preventionTips":["Signal Ready as early as possible in the capsule lifecycle; defer warm-up work","Tune readiness_timeout (500ms default) to the capsule's real init time","Test readiness signaling under load so signals aren't delayed past the window"],"tags":["timeout","readiness","health-check","capsule"],"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"}