astrid-runtime/astrid · error

daemon response timed out after 5s

Error message

daemon response timed out after 5s

What it means

The second half of doctor's daemon_roundtrip: after connecting, the GetStatus request itself is wrapped in a 5-second timeout. Elapsing it raises this error, meaning the daemon accepted the connection but did not answer GetStatus within 5s — the daemon is reachable but unresponsive (busy, deadlocked, or its request loop is stuck).

Source

Thrown at crates/astrid-cli/src/commands/doctor.rs:238

}

fn check_fail(name: &str, detail: &str) {
    println!("  [{}]  {} — {}", "FAIL".red().bold(), name.bold(), detail);
}

async fn daemon_roundtrip() -> Result<()> {
    let mut client = tokio::time::timeout(
        Duration::from_secs(5),
        crate::socket_client::connect_kernel_for_workspace(None),
    )
    .await
    .map_err(|_| anyhow::anyhow!("connection timed out after 5s"))??;
    match tokio::time::timeout(
        Duration::from_secs(5),
        client.request(KernelRequest::GetStatus),
    )
    .await
    .map_err(|_| anyhow::anyhow!("daemon response timed out after 5s"))??
    {
        KernelResponse::Status(_) => Ok(()),
        KernelResponse::Error(message) => {
            Err(anyhow::anyhow!("daemon rejected status request: {message}"))
        },
        _ => Err(anyhow::anyhow!(
            "daemon returned an unexpected status response"
        )),
    }
}

/// Query the daemon for agent-loop readiness over the same socket the
/// other daemon-dependent checks use. Rides the existing
/// `astrid.v1.request.` ingress allowlist prefix — no capsule change needed.
async fn agent_readiness() -> Result<astrid_core::kernel_api::AgentLoopReadiness> {
    let mut client = tokio::time::timeout(
        Duration::from_secs(5),
        crate::socket_client::connect_kernel_for_workspace(None),

View on GitHub (pinned to affd8760f4)

Solutions

  1. Restart the daemon and retry `astrid doctor`.
  2. Check daemon logs for a blocked/panicked handler around the time of the request.
  3. Retry when the daemon is idle (no reindex/long job running).
  4. If reproducible, capture a stack dump of the daemon to find the blocked call site.

Example fix

// before
$ astrid doctor
Error: daemon response timed out after 5s
// after
$ astrid daemon restart && astrid doctor  # daemon roundtrip: ok
Defensive patterns

Strategy: retry

Try / catch

match daemon_roundtrip().await {
    Err(e) if e.to_string().contains("daemon response timed out") => {
        eprintln!("daemon unresponsive — restart it and retry");
        restart_daemon().await?;
    },
    other => other?,
}

Prevention

When it happens

Trigger: daemon_roundtrip sends KernelRequest::GetStatus and the daemon neither replies nor errors within 5s: event loop blocked on a long task, deadlocked handler, kernel busy on a huge workspace index, or a wedged channel between the socket listener and the kernel.

Common situations: Large workspaces making status computation slow; daemon thread panics leaving the request loop hung; resource exhaustion (CPU/memory) on the host; an in-flight long operation (reindex) monopolizing the kernel.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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