{"record":{"id":"12a45b7d6d42abf9","repo":"astrid-runtime/astrid","slug":"unexpected-response-for-getstatus-other","errorCode":null,"errorMessage":"unexpected response for GetStatus: {other:?}","messagePattern":"unexpected response for GetStatus: (.+?)","errorType":"http","errorClass":"GatewayError::Internal","httpStatus":500,"severity":"error","filePath":"crates/astrid-gateway/src/routes/system.rs","lineNumber":43,"sourceCode":"        (status = 200, description = \"`DaemonStatus` JSON shape: `{ pid, started_at, uptime_secs, active_connections, ephemeral, capsules: { loaded, failed }, session_id }`.\", content_type = \"application/json\"),\n        (status = 401, body = ErrorBody),\n        (status = 403, body = ErrorBody, description = \"Caller lacks `system:status`.\"),\n    )\n)]\npub async fn get_status(\n    State(state): State<Arc<GatewayState>>,\n    req: Request<axum::body::Body>,\n) -> GatewayResult<Json<DaemonStatus>> {\n    let caller = caller_from(&req)?.clone();\n    let client = state.kernel_client_for(&caller)?;\n    let resp = client\n        .request(KernelRequest::GetStatus)\n        .await\n        .map_err(daemon_kernel_error)?;\n    match resp {\n        KernelResponse::Status(s) => Ok(Json(s)),\n        KernelResponse::Error(msg) => Err(GatewayError::Forbidden { reason: msg }),\n        other => Err(GatewayError::Internal(anyhow::anyhow!(\n            \"unexpected response for GetStatus: {other:?}\"\n        ))),\n    }\n}\n\n#[utoipa::path(\n    get,\n    path = \"/api/sys/readiness\",\n    tag = \"system\",\n    responses(\n        (status = 200, description = \"`AgentLoopReadiness` JSON shape: `{ ready: bool, prompt_subscribers: [string], response_publishers: [string], unsatisfied_required_imports: [{ capsule, namespace, interface, requirement }], loaded_capsules: [string] }`. `ready` is false when the installed capsule set can't serve an agent chat turn.\", content_type = \"application/json\"),\n        (status = 401, body = ErrorBody),\n        (status = 403, body = ErrorBody, description = \"Caller lacks `capsule:list`.\"),\n    )\n)]\npub async fn get_readiness(\n    State(state): State<Arc<GatewayState>>,\n    req: Request<axum::body::Body>,","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-gateway/src/routes/system.rs#L25-L61","documentation":"`get_status` in `system.rs` sends `KernelRequest::GetStatus` over the bus with `daemon_kernel_error` error mapping, then matches the `KernelResponse`. If the kernel replies with anything other than `Status` or `Error` — a protocol mismatch — the catch-all arm raises a 500 `GatewayError::Internal` with \"unexpected response for GetStatus\". It signals the gateway and kernel disagree on the response protocol.","triggerScenarios":"GET on the system status route when the kernel returns a `KernelResponse` variant that is neither `Status(_)` nor `Error(_)` (e.g. a variant added in a newer kernel, or a mismatched reply type routed back).","commonSituations":"Mixed-version deployment where the kernel emits a new response variant the gateway binary doesn't know; a routing bug delivering another request's response to the status caller; hand-edited or stale protocol definitions on one side.","solutions":["Read the `{other:?}` payload in logs to identify the unexpected `KernelResponse` variant.","Redeploy gateway and kernel from matching versions.","Add an explicit match arm for the observed variant in `get_status`.","Check the kernel logs for the corresponding GetStatus handling to find the source of the mismatched reply."],"exampleFix":"// before\nother => Err(GatewayError::Internal(anyhow::anyhow!(\n    \"unexpected response for GetStatus: {other:?}\"\n))),\n// after\nKernelResponse::StatusV2(s) => Ok(Json(Status::from(s))),\nother => Err(GatewayError::Internal(anyhow::anyhow!(\n    \"unexpected response for GetStatus: {other:?}\"\n))),","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn as_status(resp: KernelResponse) -> Option<Status> {\n    match resp { KernelResponse::Status(s) => Some(s), _ => None }\n}","tryCatchPattern":"match status.get_status().await {\n    Ok(s) => s,\n    Err(e) if e.message.starts_with(\"unexpected response for GetStatus\") => {\n        // protocol mismatch: check versions, retry after redeploy\n        Err(ProtocolMismatch)\n    }\n    Err(GatewayError::Forbidden { reason }) => return Err(reason.into()),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Keep gateway and kernel on the same release train; status endpoints are the first to break on drift.","Cover every `KernelResponse` variant in match arms with compile-time exhaustiveness checks.","Add a version-compatibility handshake/log line at gateway startup.","When adding a kernel response variant, update all catch-all sites in routes/system.rs in the same PR."],"tags":["gateway","kernel","response-shape","version-mismatch"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}