astrid-runtime/astrid · error · GatewayError::Internal
{msg}
Error message
{msg} What it means
internal(msg) is a helper in capsules.rs that wraps kernel-client error messages into GatewayError::Internal (500). Every capsule endpoint (list, install, get, stage, resolve_github_source, permission_cards) funnels kernel-client failures through it, so this error means the kernel/daemon side of a capsule operation failed and its message is passed through verbatim.
Solutions
- Read the embedded {msg} — it carries the kernel-client cause; treat it as the real error.
- Verify the kernel daemon is running and reachable from the gateway.
- Retry if the failure was transient (network blip during GitHub resolution or staging).
- If the message indicates a capsule-level rejection (not found, invalid source), correct the capsule id/source and re-request.
Example fix
// before: opaque 500 curl /api/capsules # 500 "kernel client: connection refused" // after: ensure kernel reachable $ systemctl status astrid-daemon && retry capsule request
Defensive patterns
Strategy: try-catch
Validate before calling
// probe kernel before capsule operations
const h = await fetch('/api/health');
if (!h.ok || h.json().kernel !== 'up') throw new Error('kernel unavailable; capsule ops disabled'); Try / catch
try {
const list = await fetch('/api/capsules');
} catch (e) {
if (e.status === 500 && /kernel/.test(e.message)) {
// daemon-side failure: check kernel health, then retry once
}
throw e;
} Prevention
- Health-check the kernel daemon before exposing capsule endpoints.
- Retry transient kernel-client errors with backoff in the helper itself.
- Surface the embedded kernel message to operators via structured logs.
- Alert on capsule endpoints' 500 rates as a proxy for gateway-kernel link health.
When it happens
Trigger: Any capsules endpoint call whose kernel client request fails — list/install/stage/get/permissions or GitHub source resolution — producing a kernel client error string mapped by internal().
Common situations: Kernel daemon down or unreachable during capsule operations; kernel rejecting a capsule id or source (message embedded in {msg}); network errors while resolving GitHub capsule sources; staging failures for capsule archives.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- daemon closed guard uplink
- daemon request
- daemon request
- daemon returned an unexpected status response
- unexpected response shape for GetCapsuleMetadata
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/dd06b2f425a0eb1f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-gateway/src/routes/capsules.rs:524
params(("id" = String, Path, description = "Capsule id")),
responses(
(status = 200, body = CapsuleTopicsResponse, description = "Declared topics. Empty until kernel-side topic enumeration ships."),
(status = 401, body = ErrorBody),
)
)]
pub async fn list_capsule_topics(
State(_state): State<Arc<GatewayState>>,
Path(_id): Path<String>,
req: Request<axum::body::Body>,
) -> GatewayResult<Json<CapsuleTopicsResponse>> {
caller_from(&req)?;
Ok(Json(CapsuleTopicsResponse { topics: vec![] }))
}
// ── helpers (kernel client error mapping) ────────────────────────
fn internal(msg: String) -> GatewayError {
GatewayError::Internal(anyhow::anyhow!(msg))
}
fn hidden_capsule_detail_denial(
caller: &astrid_core::PrincipalId,
capsule_id: &str,
reason: &str,
) -> GatewayResult<Json<CapsuleDetail>> {
tracing::warn!(
security_event = true,
principal = %caller,
capsule = %capsule_id,
reason = %reason,
"capsule detail visibility probe denied; returning hidden not-found"
);
Err(GatewayError::NotFound)
}
/// Map a non-success GitHub HTTP status to a gateway error. A `404` is aView on GitHub (pinned to affd8760f4)