astrid-runtime/astrid · error

daemon returned an unexpected status response: {other:?}

Error message

daemon returned an unexpected status response: {other:?}

What it means

status_response expects KernelResponse::Status for a GetStatus request; any other successful-shaped variant (e.g. Success, capsule-specific responses) is a protocol-level mismatch. The CLI bails with the debug representation of the unexpected response so the developer can see which variant arrived.

Source

Thrown at crates/astrid-cli/src/commands/daemon.rs:653

        println!("    - {capsule}");
    }
    Ok(())
}

fn status_document(status: Option<&DaemonStatus>) -> serde_json::Value {
    status.map_or_else(
        || serde_json::json!({ "state": "stopped" }),
        |status| serde_json::json!({ "state": "running", "daemon": status }),
    )
}

fn status_response(response: KernelResponse) -> Result<DaemonStatus> {
    match response {
        KernelResponse::Status(status) => Ok(status),
        KernelResponse::Error(message) => {
            anyhow::bail!("daemon rejected status request: {message}")
        },
        other => anyhow::bail!("daemon returned an unexpected status response: {other:?}"),
    }
}

/// Handle `astrid stop`.
///
/// A shutdown request over the socket only earns an ACK ("shutting down"), not a
/// guarantee the process exited and released the singleton/state-db lock. So we
/// capture the recorded PID BEFORE asking, then confirm the process actually
/// exits — escalating with a signal if it wedges mid-shutdown — before reporting
/// success. Runtime files (socket, readiness, PID) are removed only once the
/// daemon is confirmed gone; if a kill can't confirm exit, they are LEFT so
/// `astrid start`/`restart` still see the recorded PID and give an actionable
/// message instead of failing on the held lock with a raw DB error.
pub(crate) async fn handle_stop() -> Result<()> {
    validate_runtime_admission()?;
    // A pre-lease gateway may legitimately hold the start fence while it boots
    // its daemon. Stop the gateway first so stop can reap it; then the fence
    // linearizes the daemon phase against any other start/restart.

View on GitHub (pinned to affd8760f4)

Solutions

  1. Check version skew: compare `astrid --version` with the running daemon's PID binary (ps -p <pid> -o cmdline) and align versions.
  2. Run `astrid restart` so the daemon binary matches the CLI's protocol expectations.
  3. Ensure no other process is bound to the Astrid socket path.
  4. Rebuild/reinstall so CLI and daemon come from the same build.

Example fix

// before
$ astrid --version  # v2 CLI
$ astrid status
Error: daemon returned an unexpected status response: Success(...)
// after
$ astrid restart   # respawn daemon from the same v2 build
$ astrid status
Defensive patterns

Strategy: try-catch

Validate before calling

// detect version skew before querying
let cli_version = env!("CARGO_PKG_VERSION");
let daemon_version = /* from a prior handshake or `astrid status` once healthy */;
if cli_version != daemon_version { run(vec!["astrid", "restart"])?; }

Type guard

fn is_status(resp: &KernelResponse) -> bool {
    matches!(resp, KernelResponse::Status(_))
}

Try / catch

match status_response(client.request(KernelRequest::GetStatus).await?) {
    Ok(s) => s,
    Err(e) if e.to_string().contains("unexpected status response") => {
        run(vec!["astrid", "restart"])?; // respawn version-matched daemon
        status_response(client.request(KernelRequest::GetStatus).await?)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: KernelRequest::GetStatus answered with a KernelResponse variant other than Status or Error — typically a version-skewed daemon binary speaking a different protocol, or a proxy/relay answering with its own response type.

Common situations: Older daemon still running after a CLI upgrade (protocol drift); mixing CLI and daemon from different versions/install paths; a gateway or wrapper intercepting socket traffic and returning its own response variant.

Related errors


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