astrid-runtime/astrid · critical
candidate generation for '{id}' exited before signaling read
Error message
candidate generation for '{id}' exited before signaling ready What it means
This error is thrown when `candidate.wait_ready()` returns `ReadyStatus::Crashed`, meaning the candidate capsule process exited (crashed) before it could signal Ready. It indicates an abnormal termination during startup rather than a timeout.
Source
Thrown at crates/astrid-kernel/src/lib.rs:4722
use astrid_capsule::capsule::ReadyStatus;
let activation_timeout = std::time::Duration::from_secs(30);
let readiness_timeout = std::time::Duration::from_millis(500);
match astrid_runtime::time::timeout(activation_timeout, candidate.activate()).await {
Ok(result) => result?,
Err(_) => anyhow::bail!(
"candidate generation for '{id}' did not activate within {}ms",
activation_timeout.as_millis()
),
}
match candidate.wait_ready(readiness_timeout).await {
ReadyStatus::Ready => Ok(()),
ReadyStatus::Timeout => anyhow::bail!(
"candidate generation for '{id}' did not signal ready within {}ms",
readiness_timeout.as_millis()
),
ReadyStatus::Crashed => {
anyhow::bail!("candidate generation for '{id}' exited before signaling ready")
},
}
}
/// Attempts to restart a failed capsule, respecting backoff and max retries.
///
/// Records ONE restart attempt (advancing backoff and the retry count) per call
/// when eligible. The count is a measure of CONSECUTIVE health failures: a busy
/// capsule whose restart legitimately leaves a lingering old instance is NOT
/// treated as a failure here — the tracker is pruned by the health monitor the
/// moment the capsule RECOVERS (see the retain in [`spawn_capsule_health_monitor`]),
/// so only a capsule that keeps failing across ticks accumulates toward the cap.
/// This deliberately does not key off the [`RestartOutcome`], which is diagnostic
/// only: keying the cap off "lingering" would let a busy-but-healthy capsule
/// (whose consumer holds a clone for up to its 60s idle grace) exhaust the cap
/// and be permanently disabled.
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
async fn attempt_capsule_restart(View on GitHub (pinned to affd8760f4)
Solutions
- Inspect the capsule's logs/stderr for panics, aborts, or OOM kills during startup.
- Verify the capsule binary and its runtime dependencies (config, env, native libs) are present and valid.
- Reproduce the capsule's startup in isolation to surface the crash before it is managed by the kernel.
- Check memory limits on the host/runtime that might kill the process mid-startup.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-launch sanity: verify the capsule binary exists, is executable, and its // config/env dependencies resolve before calling activate()
Try / catch
match candidate.wait_ready(readiness_timeout).await {
ReadyStatus::Crashed => {
log::error!("capsule exited before ready; collecting stderr/coredump");
// surface capsule logs, do not blind-retry
}
_ => {}
} Prevention
- Smoke-test capsule startup in isolation before kernel-managed activation
- Pin and verify runtime dependencies (libs, env, config) in the capsule image
- Set sane memory limits so the process isn't OOM-killed at startup
- Capture and retain capsule stderr for crash diagnosis
When it happens
Trigger: `candidate.wait_ready(readiness_timeout)` returns `ReadyStatus::Crashed` — the capsule process died between activation and readiness signaling.
Common situations: Capsule panics or aborts during initialization; missing runtime dependencies (shared libs, config, env vars) causing immediate exit; bad binary/entrypoint; OOM kill of the capsule process during startup.
Related errors
- detached FUSE service failed: {message}
- WinFsp daemon did not report readiness within 30 seconds
- cannot remove capsule authority while an install transaction
- an incomplete capsule authority update exists at {}; remove
- unsupported installed authority schema {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/8e31c014df211b96.
Report an issue: GitHub.