astrid-runtime/astrid · error · GatewayError::Internal
gateway is not wired to a live event bus; admin operations…
Error message
gateway is not wired to a live event bus; admin operations unavailable
What it means
An admin bus operation was requested but the GatewayState was constructed without an event bus. BusAdminClient needs a live bus connection to reach the daemon; without it, no admin operation can proceed, so admin_client() returns GatewayError::Internal. In production the daemon always wires the bus, so this normally indicates a standalone/test or misconfigured gateway.
Solutions
- Wire the event bus into GatewayState at construction time (use the production constructor/daemon wiring path)
- Check gateway startup config so the event bus is initialized before routes are served
- Guard admin routes to return 503/404 when running in standalone mode instead of exercising the bus
- In tests, build the state with a live (in-memory) bus rather than the tests-only constructor
Example fix
// before let state = GatewayState::new_standalone(config); // no event_bus // after let state = GatewayState::new(config, event_bus, session_id)?; // wired
Defensive patterns
Strategy: validation
Validate before calling
fn admin_ready(state: &GatewayState) -> bool {
state.event_bus.is_some()
} Type guard
fn wired_bus(state: &GatewayState) -> Option<Arc<EventBus>> {
state.event_bus.clone()
} Try / catch
match state.admin_client(caller) {
Ok(client) => use_client(client).await,
Err(GatewayError::Internal(e)) if e.to_string().contains("not wired to a live event bus") => {
Err(StatusCode::SERVICE_UNAVAILABLE)
}
Err(e) => Err(e.into()),
} Prevention
- Always construct GatewayState through the production wiring path that sets event_bus
- Add a readiness probe that fails startup if the bus is not wired
- Return 503 from admin routes when the gateway is in standalone mode
When it happens
Trigger: Calling admin_client() (directly or via admin_client_for / assert_live_audit_revocation) on a GatewayState built by the tests-only constructor or a bootstrap path that leaves the event_bus field None.
Common situations: Running the gateway in standalone/dev mode without bus wiring; a configuration path that skips event-bus initialization; unit tests exercising admin endpoints against an unwired state.
Related errors
- gateway is not wired to a live event bus; agent approval…
- gateway is not wired to a live event bus; kernel requests…
- gateway is not wired to a live event bus; model registry…
- gateway is not wired to a live kernel session; admin…
- Admin request timed out after
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/1278b727c4d824da.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-gateway/src/state.rs:419
Ok(())
}
/// Build a bus-direct admin client bound to `caller`. Routes
/// hosted in this same process talk to the kernel over the
/// 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.
///View on GitHub (pinned to affd8760f4)