astrid-runtime/astrid · error · GatewayError::Internal
gateway is not wired to a live kernel session; admin…
Error message
gateway is not wired to a live kernel session; admin operations unavailable
What it means
An admin bus operation was requested while the gateway has an event bus but no kernel session id. BusAdminClient requires the session id to address the live kernel session, so admin_client() returns GatewayError::Internal when session_id is None.
Solutions
- Ensure the kernel session handshake completes and stores the session id before serving admin routes
- Check startup logs for session registration failures and fix the underlying connect error
- Delay/readiness-gate admin endpoints until state.session_id is Some
- Fix the construction site to pass the session id alongside the event bus
Example fix
// before let state = GatewayState::new(config, event_bus, None)?; // after let session = connect_kernel_session(&event_bus).await?; let state = GatewayState::new(config, event_bus, Some(session.id()))?;
Defensive patterns
Strategy: validation
Validate before calling
fn admin_session_ready(state: &GatewayState) -> bool {
state.event_bus.is_some() && state.session_id.is_some()
} Type guard
fn live_session(state: &GatewayState) -> Option<SessionId> {
state.session_id.as_ref().map(|s| s.0)
} Try / catch
if state.session_id.is_none() {
return Err(StatusCode::SERVICE_UNAVAILABLE); // session not established yet
}
let client = state.admin_client(caller)?; Prevention
- Only expose admin routes after the kernel session handshake stores session_id
- Fail fast at startup if session registration does not succeed
- Poll state.session_id in readiness checks before accepting admin traffic
When it happens
Trigger: Calling admin_client() / admin_client_for() / assert_live_audit_revocation() on a state where event_bus is Some but session_id is None — e.g. the bus was wired before the gateway completed its kernel session handshake, or the handshake failed silently.
Common situations: Admin requests arriving during startup before session establishment; the kernel session registration step failed or was skipped in a custom embedding of the gateway; test setups that set a bus but never a session id.
Related errors
- gateway is not wired to a live event bus; admin operations…
- gateway is not wired to a live kernel session; kernel…
- Admin request timed out after
- Astrid volume path has no file name
- canonical Astrid workspace requires the kernel workspace…
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/52c940a454cbcfea.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-gateway/src/state.rs:424
/// shared event bus rather than the Unix socket — bypasses the
/// `astrid-capsule-cli` proxy entirely and removes the 19 RPS
/// admin-throughput ceiling the socket path imposes.
///
/// # Errors
/// Returns an internal error if the state was built without a
/// live event bus (the standalone tests-only constructor). In
/// production the daemon always wires it up.
pub fn admin_client(
&self,
caller: astrid_core::PrincipalId,
) -> Result<crate::bus_admin::BusAdminClient, crate::error::GatewayError> {
let bus = self.event_bus.clone().ok_or_else(|| {
crate::error::GatewayError::Internal(anyhow::anyhow!(
"gateway is not wired to a live event bus; admin operations unavailable"
))
})?;
let session_id = self.session_id.as_ref().ok_or_else(|| {
crate::error::GatewayError::Internal(anyhow::anyhow!(
"gateway is not wired to a live kernel session; admin operations unavailable"
))
})?;
Ok(crate::bus_admin::BusAdminClient::new(
bus,
caller,
session_id.0,
))
}
/// Build a bus-direct admin client for an authenticated caller, carrying
/// the caller's device scope through to the kernel cap-gate.
///
/// Use this for every admin op behind the auth middleware: it stamps the
/// caller's `device_key_id` (when the bearer was device-scoped) onto each
/// outbound request so a paired device's scope is enforced kernel-side.
/// The two unauthenticated redeem routes (which act as the bootstrap
/// `default` principal) keep [`admin_client`](Self::admin_client) — theirView on GitHub (pinned to affd8760f4)