astrid-runtime/astrid · error
kernel returned an unexpected projection-name diagnostic res
Error message
kernel returned an unexpected projection-name diagnostic response
What it means
Raised by the public method `projection_name_diagnostic` in `astrid-uplink/src/kernel_client.rs:345`. When the awaited reply is neither `KernelResponse::Success` nor `KernelResponse::Error` — falling into the catch-all `_` arm — the client cannot interpret the kernel's response shape and throws this error. It indicates a protocol violation or version mismatch between the client and the kernel on the diagnostic response channel.
Source
Thrown at crates/astrid-uplink/src/kernel_client.rs:345
"params": { "policy": policy },
});
let (message, response_topic) = build_named_request_message(
&self.caller,
self.device_key_id.as_deref(),
PROJECTION_NAME_DIAGNOSTIC_TOPIC,
payload,
);
match self
.send_and_wait(message, response_topic, MAX_TOTAL)
.await?
{
KernelResponse::Success(value) => {
serde_json::from_value(value).context("decode projection-name diagnostic response")
},
KernelResponse::Error(message) => Err(anyhow!(
"kernel rejected projection-name diagnostic: {message}"
)),
_ => Err(anyhow!(
"kernel returned an unexpected projection-name diagnostic response"
)),
}
}
/// [`request`](Self::request) with an explicit overall ceiling.
///
/// The public entrypoint passes [`MAX_TOTAL`]; a test passes a short ceiling
/// so the "unending keepalives are bounded" path is exercisable without
/// waiting ten minutes. Production behaviour is unchanged.
async fn request_with_ceiling(
&mut self,
req: KernelRequest,
max_total: Duration,
) -> std::result::Result<KernelResponse, KernelClientError> {
let (msg, want_response) =
build_request_message(&self.caller, self.device_key_id.as_deref(), &req)
.map_err(|source| KernelClientError::Build { source })?;View on GitHub (pinned to affd8760f4)
Solutions
- Upgrade the astrid-uplink client and kernel daemon to matching versions so the diagnostic response schema agrees.
- Ensure each request uses a unique response topic so no other kernel frame can be matched against it.
- Log the actual `KernelResponse` variant received (add a debug print before the match) to identify what the kernel returned.
- Retry once after re-establishing the socket in case a stale/misrouted frame was in flight; if it persists, file a protocol bug.
Example fix
// before
KernelResponse::Error(message) => Err(anyhow!(
"kernel rejected projection-name diagnostic: {message}"
)),
_ => Err(anyhow!(
"kernel returned an unexpected projection-name diagnostic response"
)),
// after (make the unexpected case debuggable)
_ => {
debug!(?response, "unexpected projection-name diagnostic response");
Err(anyhow!(
"kernel returned an unexpected projection-name diagnostic response: {response:?}"
))
} Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure a dedicated response topic per request to avoid cross-talk
let response_topic = format!("diag/{}/{}", Uuid::new_v4(), name); Type guard
fn matches_diag_response(resp: &KernelResponse) -> bool {
matches!(resp, KernelResponse::Success(_) | KernelResponse::Error(_))
} Try / catch
let resp = send_and_wait(message, response_topic, MAX_TOTAL).await?;
if !matches_diag_response(&resp) {
debug!(?resp, "unexpected kernel response shape");
bail!("kernel returned an unexpected projection-name diagnostic response: {resp:?}");
} Prevention
- Use a unique response topic per in-flight request so unrelated kernel frames cannot be misinterpreted.
- Pin client and kernel to the same release train; response framing changed across versions historically.
- Log unexpected variants at debug level to make protocol skew visible in the field.
When it happens
Trigger: Specifically: `send_and_wait` for the projection-name diagnostic returns a `KernelResponse` variant outside `{Success, Error}` (e.g. an event/other frame type arrived on the response topic), so the match falls through to the wildcard arm. Cross-talk on the response topic or an unexpected kernel frame can also land here.
Common situations: Client and kernel built from mismatched versions where the diagnostic reply encoding changed; another message was routed to the same response topic and matched first; a kernel bug emitting a non-standard frame for this request; multiplexed topics where two in-flight diagnostics share a topic string.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- kernel rejected request: {msg}
- daemon returned an unexpected status response: {other:?}
- unexpected response from kernel: {other:?}
- kernel returned an unexpected storage lifecycle response
- kernel rejected request: {msg}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/6c872f308797a2fc.
Report an issue: GitHub.