{"record":{"id":"81d385e74a10beb9","repo":"astrid-runtime/astrid","slug":"kernel-rejected-projection-name-diagnostic-messa","errorCode":null,"errorMessage":"kernel rejected projection-name diagnostic: {message}","messagePattern":"kernel rejected projection-name diagnostic: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-uplink/src/kernel_client.rs","lineNumber":342,"sourceCode":"    ) -> Result<ProjectionNameDiagnostic> {\n        let payload = serde_json::json!({\n            \"method\": PROJECTION_NAME_DIAGNOSTIC_METHOD,\n            \"params\": { \"policy\": policy },\n        });\n        let (message, response_topic) = build_named_request_message(\n            &self.caller,\n            self.device_key_id.as_deref(),\n            PROJECTION_NAME_DIAGNOSTIC_TOPIC,\n            payload,\n        );\n        match self\n            .send_and_wait(message, response_topic, MAX_TOTAL)\n            .await?\n        {\n            KernelResponse::Success(value) => {\n                serde_json::from_value(value).context(\"decode projection-name diagnostic response\")\n            },\n            KernelResponse::Error(message) => Err(anyhow!(\n                \"kernel rejected projection-name diagnostic: {message}\"\n            )),\n            _ => Err(anyhow!(\n                \"kernel returned an unexpected projection-name diagnostic response\"\n            )),\n        }\n    }\n\n    /// [`request`](Self::request) with an explicit overall ceiling.\n    ///\n    /// The public entrypoint passes [`MAX_TOTAL`]; a test passes a short ceiling\n    /// so the \"unending keepalives are bounded\" path is exercisable without\n    /// waiting ten minutes. Production behaviour is unchanged.\n    async fn request_with_ceiling(\n        &mut self,\n        req: KernelRequest,\n        max_total: Duration,\n    ) -> std::result::Result<KernelResponse, KernelClientError> {","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-uplink/src/kernel_client.rs#L324-L360","documentation":"Raised by the public method `projection_name_diagnostic` in `astrid-uplink/src/kernel_client.rs:342`. After sending a projection-name diagnostic request and awaiting the response, a `KernelResponse::Error(message)` variant is converted into this error carrying the kernel's message. It means the kernel understood the request but refused it, and the kernel's reason is embedded in the error text.","triggerScenarios":"Specifically: `send_and_wait(message, response_topic, MAX_TOTAL)` returns `KernelResponse::Error(message)` while awaiting a projection-name diagnostic reply. The kernel-side diagnostic handler rejected the request (invalid projection name, diagnostic subsystem unavailable, permission or state error).","commonSituations":"Querying a projection name that does not exist or violates kernel naming rules; the kernel's diagnostic facility is disabled in the running configuration; client/kernel version skew where the diagnostic request no longer matches what the kernel expects; sending the diagnostic before the kernel finished initializing projections.","solutions":["Read `{message}` — it contains the kernel's specific rejection reason for the diagnostic.","Validate the projection name against kernel naming rules before requesting the diagnostic.","Confirm the kernel is fully initialized and the diagnostic feature is enabled in its config.","Align client and kernel versions if the diagnostic request schema changed between releases.","Only retry after changing the request; a deterministic kernel rejection will recur identically."],"exampleFix":"// before\nlet diag = kernel.projection_name_diagnostic(name).await?;\n// after\nlet diag = kernel.projection_name_diagnostic(name).await.map_err(|e| {\n    if e.to_string().contains(\"unknown projection\") {\n        bail!(\"projection {name} does not exist on the kernel\");\n    }\n    e\n})?;","handlingStrategy":"try-catch","validationCode":"// Validate the projection name client-side before requesting a diagnostic\nif name.is_empty() || !name.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_') {\n    bail!(\"invalid projection name: {name:?}\");\n}","typeGuard":"fn is_kernel_error(resp: &KernelResponse) -> Option<&str> {\n    match resp {\n        KernelResponse::Error(m) => Some(m),\n        _ => None,\n    }\n}","tryCatchPattern":"let diag = match kernel.projection_name_diagnostic(&name).await {\n    Ok(d) => d,\n    Err(e) => {\n        warn!(error = %e, name, \"projection-name diagnostic rejected\");\n        return Err(e);\n    }\n};","preventionTips":["Validate projection names against kernel rules before issuing diagnostics.","Verify the kernel's diagnostic subsystem is enabled in its configuration.","Keep client and kernel versions aligned; the diagnostic schema can change between releases.","Send diagnostics only after the kernel reports readiness."],"tags":["kernel","ipc","diagnostics","rpc","projection"],"backgroundTag":"http-error-response","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}