astrid-runtime/astrid · warning
Daemon is still starting after {timeout_secs} seconds; it wa
Error message
Daemon is still starting after {timeout_secs} seconds; it was left running. Check logs or run `astrid status` / retry later.{} What it means
If the freshly spawned daemon is still alive but has not written its readiness sentinel within the configured spawn timeout, wait_for_ready returns StillRunning and this error is raised. The CLI deliberately does not kill the child (a first-run layout-1 audit import can outlive the wait); it disowns the process and tells the operator to retry later rather than losing a healthy boot in progress.
Source
Thrown at crates/astrid-cli/src/commands/daemon.rs:134
let mut child = cmd
.spawn()
.context("Failed to spawn background Kernel daemon")?;
// Poll for the readiness sentinel instead of the socket file.
// The readiness file is written only after load_all_capsules()
// completes (including await_capsule_readiness()), so the accept
// loop is guaranteed to be running by the time we connect.
let timeout_secs = configured_spawn_timeout_secs(workspace_root);
match wait_for_ready(ready_path, &mut child, timeout_secs).await {
ReadyWaitOutcome::Ready => Ok(child),
ReadyWaitOutcome::ChildExited(status) => {
anyhow::bail!("Daemon exited prematurely ({status}).{}", log_hint());
},
ReadyWaitOutcome::StillRunning => {
// Do not SIGKILL a live first cutover (layout-1 audit import
// can outlive the wait). Disown and tell the operator.
disown_if_still_running(child);
anyhow::bail!(
"Daemon is still starting after {timeout_secs} seconds; it was left running. Check logs or run `astrid status` / retry later.{}",
log_hint()
);
},
}
}
fn ephemeral_daemon_command(daemon_bin: &Path, workspace_root: &Path) -> std::process::Command {
let mut cmd = std::process::Command::new(daemon_bin);
cmd.arg("--ephemeral")
.arg("--workspace")
.arg(workspace_root)
.env(
"ASTRID_WORKSPACE_STATE_DIR",
crate::workspace_layout::current().state_dir_name(),
);
cmd
}View on GitHub (pinned to affd8760f4)
Solutions
- Wait and retry: the daemon was left running; run `astrid status` until it reports ready, then re-run your command.
- Increase the configured spawn timeout (the env/config knob behind configured_spawn_timeout_secs) on slow machines or large workspaces.
- Check the daemon log to confirm it is performing a first cutover/import rather than deadlocked.
- If the daemon is actually wedged (no log progress), kill it and run `astrid restart` for a clean boot.
Example fix
# before: default timeout too small for a big first import $ astrid start # error after 30s # after $ ASTRID_SPAWN_TIMEOUT_SECS=600 astrid start # or: wait and `astrid status`
Defensive patterns
Strategy: retry
Validate before calling
// Confirm the readiness file is merely slow (not a failed boot) before retrying
fn boot_alive_and_pending(ready_path: &Path, pid_path: &Path) -> bool {
recorded_daemon_pid_is_alive() && !ready_path.exists()
} Try / catch
match spawn_daemon_inner(ready_path, announce, None).await {
Err(e) if e.to_string().contains("still starting after") => {
// Daemon was disowned, not killed. Poll readiness ourselves with a longer budget.
for _ in 0..120 {
if ready_path.exists() { return ensure_daemon_workspace_matches(None).await; }
tokio::time::sleep(Duration::from_secs(5)).await;
}
anyhow::bail!("daemon still not ready after extended wait; check logs or run `astrid status`")
},
other => other,
} Prevention
- Increase the spawn timeout (configured_spawn_timeout_secs) on slow machines or large first-run imports.
- Expect slow first cutover/audit imports; poll `astrid status` instead of immediately restarting.
- Watch the daemon boot log to confirm import progress before assuming a hang.
- Only kill the disowned daemon if the log shows no progress for an extended period.
When it happens
Trigger: spawn_daemon -> spawn_daemon_inner with wait_for_ready exhausting timeout_secs while the daemon process keeps running — typically a slow first cutover/audit import, a large workspace, or an overloaded machine.
Common situations: First run on a big existing workspace where layout migration/import takes minutes; slow disk or container CPU throttling; spawn timeout configured too low (configured_spawn_timeout_secs); readiness file path on a filesystem with delayed visibility (e.g. some network mounts).
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Daemon exited prematurely ({status}).{}
- daemon workspace metadata was not available within {timeout_
- an Astrid daemon appears to be running but its uplink is unr
- WinFsp daemon did not report readiness within 30 seconds
- Admin request timed out after {:?} waiting for {want_respons
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/128b8aa79613710b.
Report an issue: GitHub.