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

  1. Upgrade the astrid-uplink client and kernel daemon to matching versions so the diagnostic response schema agrees.
  2. Ensure each request uses a unique response topic so no other kernel frame can be matched against it.
  3. Log the actual `KernelResponse` variant received (add a debug print before the match) to identify what the kernel returned.
  4. 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

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


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