{"record":{"id":"0f3be7ab5b583b33","repo":"astrid-runtime/astrid","slug":"daemon-rejected-status-request-message","errorCode":null,"errorMessage":"daemon rejected status request: {message}","messagePattern":"daemon rejected status request: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/daemon.rs","lineNumber":651,"sourceCode":"    println!(\"  Capsules:   {} loaded\", status.loaded_capsules.len());\n    for capsule in &status.loaded_capsules {\n        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","sourceCodeStart":633,"sourceCodeEnd":669,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/daemon.rs#L633-L669","documentation":"status_response maps the kernel's reply to a DaemonStatus. When the daemon answers the GetStatus request with KernelResponse::Error, the CLI surfaces the daemon-supplied reason verbatim prefixed with 'daemon rejected status request:'. The connection and protocol worked; the daemon itself refused to serve a status report.","triggerScenarios":"Sending KernelRequest::GetStatus over the socket and receiving KernelResponse::Error(message) from the daemon — i.e. the daemon's request handler explicitly rejected the status query with some internal reason string.","commonSituations":"Daemon degraded state (state DB locked, capsule load failure, internal handler error) at the moment status was queried; daemon built from a mismatched version with runtime invariants failing; querying during shutdown when handlers already began unwinding.","solutions":["Read the embedded {message} — it names the daemon-side reason and dictates the fix.","Retry `astrid status` — transient rejections (e.g. brief lock contention) often clear.","Run `astrid restart` if the daemon is persistently degraded.","Check daemon logs for the matching internal error to fix the root cause."],"exampleFix":"// before\nlet status = status_response(client.request(KernelRequest::GetStatus).await?)?;\n// after (retry transient rejections)\nlet status = match client.request(KernelRequest::GetStatus).await {\n    Ok(r @ KernelResponse::Status(_)) => status_response(r)?,\n    Ok(KernelResponse::Error(msg)) => { tokio::time::sleep(Duration::from_secs(1)).await; status_response(client.request(KernelRequest::GetStatus).await?)? }\n    other => status_response(other?)?,\n};","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"fn status_of(resp: &KernelResponse) -> Option<&DaemonStatus> {\n    match resp { KernelResponse::Status(s) => Some(s), _ => None }\n}","tryCatchPattern":"let resp = client.request(KernelRequest::GetStatus).await?;\nlet status = match status_response(resp) {\n    Ok(s) => s,\n    Err(e) if e.to_string().starts_with(\"daemon rejected status request\") => {\n        eprintln!(\"daemon degraded: {e}; retrying or restarting\");\n        run(vec![\"astrid\", \"restart\"])?;\n        status_response(client.request(KernelRequest::GetStatus).await?)?\n    }\n    Err(e) => return Err(e),\n};","preventionTips":["Watch daemon logs — the embedded message names the internal handler that rejected the query.","Avoid querying status during startup/shutdown windows; wait for readiness markers.","Keep daemon and CLI versions aligned to reduce degraded-handler states.","Retry once before restarting: many rejections are transient lock contention."],"tags":["daemon","ipc","rpc","status"],"backgroundTag":"api-error-response","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"}