{"record":{"id":"1d32795c3bd6d4ea","repo":"astrid-runtime/astrid","slug":"daemon-returned-an-unexpected-status-response-ot","errorCode":null,"errorMessage":"daemon returned an unexpected status response: {other:?}","messagePattern":"daemon returned an unexpected status response: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/daemon.rs","lineNumber":653,"sourceCode":"        println!(\"    - {capsule}\");\n    }\n    Ok(())\n}\n\nfn status_document(status: Option<&DaemonStatus>) -> serde_json::Value {\n    status.map_or_else(\n        || serde_json::json!({ \"state\": \"stopped\" }),\n        |status| serde_json::json!({ \"state\": \"running\", \"daemon\": status }),\n    )\n}\n\nfn status_response(response: KernelResponse) -> Result<DaemonStatus> {\n    match response {\n        KernelResponse::Status(status) => Ok(status),\n        KernelResponse::Error(message) => {\n            anyhow::bail!(\"daemon rejected status request: {message}\")\n        },\n        other => anyhow::bail!(\"daemon returned an unexpected status response: {other:?}\"),\n    }\n}\n\n/// Handle `astrid stop`.\n///\n/// A shutdown request over the socket only earns an ACK (\"shutting down\"), not a\n/// guarantee the process exited and released the singleton/state-db lock. So we\n/// capture the recorded PID BEFORE asking, then confirm the process actually\n/// exits — escalating with a signal if it wedges mid-shutdown — before reporting\n/// success. Runtime files (socket, readiness, PID) are removed only once the\n/// daemon is confirmed gone; if a kill can't confirm exit, they are LEFT so\n/// `astrid start`/`restart` still see the recorded PID and give an actionable\n/// message instead of failing on the held lock with a raw DB error.\npub(crate) async fn handle_stop() -> Result<()> {\n    validate_runtime_admission()?;\n    // A pre-lease gateway may legitimately hold the start fence while it boots\n    // its daemon. Stop the gateway first so stop can reap it; then the fence\n    // linearizes the daemon phase against any other start/restart.","sourceCodeStart":635,"sourceCodeEnd":671,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/daemon.rs#L635-L671","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check version skew: compare `astrid --version` with the running daemon's PID binary (ps -p <pid> -o cmdline) and align versions.","Run `astrid restart` so the daemon binary matches the CLI's protocol expectations.","Ensure no other process is bound to the Astrid socket path.","Rebuild/reinstall so CLI and daemon come from the same build."],"exampleFix":"// before\n$ astrid --version  # v2 CLI\n$ astrid status\nError: daemon returned an unexpected status response: Success(...)\n// after\n$ astrid restart   # respawn daemon from the same v2 build\n$ astrid status","handlingStrategy":"try-catch","validationCode":"// detect version skew before querying\nlet cli_version = env!(\"CARGO_PKG_VERSION\");\nlet daemon_version = /* from a prior handshake or `astrid status` once healthy */;\nif cli_version != daemon_version { run(vec![\"astrid\", \"restart\"])?; }","typeGuard":"fn is_status(resp: &KernelResponse) -> bool {\n    matches!(resp, KernelResponse::Status(_))\n}","tryCatchPattern":"match status_response(client.request(KernelRequest::GetStatus).await?) {\n    Ok(s) => s,\n    Err(e) if e.to_string().contains(\"unexpected status response\") => {\n        run(vec![\"astrid\", \"restart\"])?; // respawn version-matched daemon\n        status_response(client.request(KernelRequest::GetStatus).await?)?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always `astrid restart` after upgrading the CLI so the daemon binary matches.","Ensure only one astrid build is on PATH; remove stale installs.","Check that no wrapper/gateway process is bound to the Astrid socket.","Pin daemon+CLI versions together in deployment manifests."],"tags":["daemon","ipc","protocol","version-skew"],"backgroundTag":"unexpected-response-shape","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}