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

  1. Wait and retry: the daemon was left running; run `astrid status` until it reports ready, then re-run your command.
  2. Increase the configured spawn timeout (the env/config knob behind configured_spawn_timeout_secs) on slow machines or large workspaces.
  3. Check the daemon log to confirm it is performing a first cutover/import rather than deadlocked.
  4. 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

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

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/128b8aa79613710b. Report an issue: GitHub.