{"record":{"id":"c66252ba5a28381b","repo":"astrid-runtime/astrid","slug":"daemon-request-e-c66252","errorCode":null,"errorMessage":"daemon request: {e}","messagePattern":"daemon request: (.+?)","errorType":"http","errorClass":"GatewayError::Internal","httpStatus":500,"severity":"error","filePath":"crates/astrid-gateway/src/routes/invites.rs","lineNumber":93,"sourceCode":"        .extensions()\n        .get::<CallerContext>()\n        .cloned()\n        .ok_or(GatewayError::Unauthorized)?;\n    let bytes = axum::body::to_bytes(req.into_body(), 64 * 1024)\n        .await\n        .map_err(|e| GatewayError::BadRequest(format!(\"body read: {e}\")))?;\n    let body: IssueRequest = serde_json::from_slice(&bytes)?;\n\n    let client = state.admin_client_for(&caller)?;\n    let resp = client\n        .request(AdminRequestKind::InviteIssue {\n            group: body.group,\n            expires_secs: body.expires_secs,\n            max_uses: body.max_uses,\n            metadata: body.metadata,\n        })\n        .await\n        .map_err(|e| GatewayError::Internal(anyhow::anyhow!(\"daemon request: {e}\")))?;\n    match resp {\n        AdminResponseBody::Invite(invite) => Ok(Json(IssueResponse { invite })),\n        AdminResponseBody::Error(msg) => Err(GatewayError::Forbidden { reason: msg }),\n        other => Err(GatewayError::Internal(anyhow::anyhow!(\n            \"unexpected response shape: {other:?}\"\n        ))),\n    }\n}\n\n/// `OpenAPI` schema mirror of [`astrid_core::kernel_api::InviteSummary`].\n/// Never constructed; resolves the `value_type` on\n/// [`ListResponse::invites`] to a typed schema. Keep it\n/// field-for-field with the serialized shape of `InviteSummary` —\n/// note the field is `token_fingerprint` (not `fingerprint`), and\n/// `issued_at_epoch` is always present.\n#[derive(ToSchema)]\npub struct InviteSummaryView {\n    /// Domain-separated `blake3:<hex>` fingerprint of the token. Raw tokens are never","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-gateway/src/routes/invites.rs#L75-L111","documentation":"issue_invite forwards the invite request to the daemon via the admin client; any transport or request failure is wrapped as an Internal error with context 'daemon request: {e}'. This indicates the gateway could not complete the round-trip to the daemon, as opposed to the daemon rejecting the invite itself (which becomes Forbidden).","triggerScenarios":"The client.request(AdminRequestKind::InviteIssue) future fails — daemon socket not reachable, connection dropped, timeout, or serialization failure while sending the invite issue request.","commonSituations":"Daemon process not running; wrong daemon socket/address in gateway config; daemon restarting during a request; permission denied on the unix socket.","solutions":["Check that the daemon process is running and its socket/address matches the gateway's admin client config","Inspect the wrapped source error (`e`) in logs to distinguish connection-refused vs timeout vs permission issues","Retry the invite issuance after confirming daemon health"],"exampleFix":"// before\n.map_err(|e| GatewayError::Internal(anyhow::anyhow!(\"daemon request: {e}\")))?;\n// after\n.map_err(|e| {\n    tracing::error!(error = %e, \"daemon request failed while issuing invite\");\n    GatewayError::Internal(anyhow::anyhow!(\"daemon request: {e}\"))\n})?;","handlingStrategy":"try-catch","validationCode":"// Probe daemon reachability before issuing the invite\nclient.request(AdminRequestKind::Ping).await\n    .map_err(|_| anyhow::anyhow!(\"daemon unreachable\"))?;","typeGuard":null,"tryCatchPattern":"match issue_invite(State(state), caller, Json(body)).await {\n    Ok(resp) => resp,\n    Err(GatewayError::Internal(e)) if e.to_string().starts_with(\"daemon request\") => {\n        tracing::error!(%e, \"daemon unreachable during invite issuance\");\n        service_unavailable(\"daemon temporarily unavailable; retry\")\n    }\n    Err(GatewayError::Forbidden { reason }) => forbidden(reason),\n    Err(e) => internal_error(e),\n}","preventionTips":["Monitor daemon health (socket reachability) and alert before user requests fail","Pin the daemon socket path in config and verify it after redeploys","Implement a bounded retry for transient IPC failures on invite issuance"],"tags":["rust","ipc","daemon","network","gateway"],"backgroundTag":"api-request-failed","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"}