astrid-runtime/astrid · error · GatewayError::Internal
daemon request: {e}
Error message
daemon request: {e} What it means
post_redeem (invite redemption) maps any failure of the admin/daemon client request into an Internal (500) error "daemon request: {e}". It means the gateway could not get a successful response from the kernel/daemon for the InviteRedeem admin request — transport, connection, or client-level failure.
Source
Thrown at crates/astrid-gateway/src/routes/auth.rs:137
.max(1),
});
}
}
// `InviteRedeem` doesn't need a verified caller principal — the
// token is the auth and the kernel's admin dispatcher bypasses
// the cap-gate for this variant. Stamp the IPC message with the
// `default` principal so the kernel's `resolve_caller` has *a*
// value to log; the handler ignores it.
let client = state.admin_client(PrincipalId::default())?;
let resp = client
.request(AdminRequestKind::InviteRedeem {
token: body.token,
public_key: body.public_key,
display_name: body.display_name,
})
.await
.map_err(|e| GatewayError::Internal(anyhow::anyhow!("daemon request: {e}")))?;
let redeemed = match resp {
AdminResponseBody::InviteRedeemed(r) => r,
AdminResponseBody::Error(msg) => return Err(GatewayError::Kernel(msg)),
other => {
return Err(GatewayError::Internal(anyhow::anyhow!(
"unexpected response shape: {other:?}"
)));
},
};
let session_token = mint_bearer(
&state.signing.signer,
&redeemed.principal,
state.config.session_lifetime_secs,
);
let session_expires_at_epoch = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map_or(0, |d| d.as_secs())View on GitHub (pinned to affd8760f4)
Solutions
- Check the daemon is running and reachable (socket/address in gateway config).
- Look at the wrapped {e} message for the exact transport failure (connection refused vs timeout).
- Redeploy/restart the kernel daemon if it crashed, then retry redemption.
- Verify gateway-to-daemon configuration matches the daemon's actual listen address.
Example fix
// before: config pointing at a dead socket admin_addr = "/run/astrid/daemon.sock" // after: ensure daemon is up and address correct $ systemctl status astrid-daemon # then restart gateway
Defensive patterns
Strategy: retry
Validate before calling
// precheck daemon reachability before redemption
const ok = await fetch('/api/health'); // gateway health implies daemon link
if (!ok.ok) throw new Error('daemon unreachable; retry later'); Try / catch
match client.request(AdminRequestKind::InviteRedeem { .. }).await {
Ok(resp) => resp,
Err(e) if e.is_connect() || e.is_timeout() => backoff_retry(|| client.request(req.clone())).await
.map_err(|e| GatewayError::Internal(anyhow!("daemon request: {e}")))?,
Err(e) => return Err(GatewayError::Internal(anyhow!("daemon request: {e}"))),
} Prevention
- Monitor daemon liveness and alert on restarts.
- Use systemd/socket supervision so the daemon auto-recovers.
- Set sane request timeouts and retry idempotent admin requests.
- Validate daemon address config during deployment health checks.
When it happens
Trigger: POST /api/auth/redeem where client.request(AdminRequestKind::InviteRedeem{...}).await returns Err — daemon unreachable, connection refused, request timeout, or serialization failure.
Common situations: Kernel daemon not running or crashed; wrong daemon socket/URL configured; network partition between gateway and daemon; daemon overloaded and timing out.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- daemon request: {e}
- capsules are installed, but connecting to the selected works
- failed to fetch {name} from {url} (HTTP {})
- daemon closed guard uplink
- {label} download failed: HTTP {status}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/cff32c7525851836.
Report an issue: GitHub.