astrid-runtime/astrid · error · GatewayError::Internal
gateway is not wired to a live event bus; model registry una
Error message
gateway is not wired to a live event bus; model registry unavailable
What it means
`registry_round_trip` requires the gateway `AppState` to have a live event bus (`state.event_bus`). If the bus is `None`, the function immediately returns `GatewayError::Internal` with the message 'gateway is not wired to a live event bus; model registry unavailable'. This is a wiring/deployment problem: model list/get/set endpoints cannot function without an event bus.
Source
Thrown at crates/astrid-gateway/src/routes/models.rs:198
///
/// `corr_id` is the set-path correlation filter (see
/// [`reply_satisfies_corr_id`]). When `Some`, the reply-draining loop SKIPS
/// any reply whose `corr_id` is present and differs from ours — that reply
/// belongs to another concurrent same-principal SET — and keeps receiving
/// (within the same overall timeout budget) until a matching / un-correlated
/// reply arrives or the budget is spent. When `None` (the GET paths) the
/// first trusted-source reply on the scoped route is taken.
async fn registry_round_trip(
state: &GatewayState,
principal_id: &PrincipalId,
_workspace: &WorkspaceContext,
request_topic: &'static str,
response_topic: &'static str,
payload: serde_json::Value,
corr_id: Option<&str>,
) -> GatewayResult<serde_json::Value> {
let Some(bus) = state.event_bus.clone() else {
return Err(GatewayError::Internal(anyhow::anyhow!(
"gateway is not wired to a live event bus; model registry unavailable"
)));
};
let principal = principal_id.to_string();
ensure_registry_request_subscribed(state, principal_id, request_topic).await?;
let expected_source_ids = provider_source_ids(state, principal_id, request_topic).await?;
// Subscribe FIRST, then publish. Reverse order would race a fast
// registry reply — the reply could land before subscribe returns and
// we'd miss it. The route is scoped to `Some(Some(principal))`: the
// outer `Some` marks the route as scoped, the inner `Some(principal)`
// is the security boundary — a reply stamped with any other principal
// is dropped at enqueue and never enters this route's budget. A fresh
// per-call UUID isolates this connection's route from any concurrent
// model request.
let mut reply_rx = bus.subscribe_topic_routed_scoped(
Uuid::new_v4(),View on GitHub (pinned to affd8760f4)
Solutions
- Check gateway startup config and logs for event-bus initialization; fix the wiring so `state.event_bus` is populated.
- If intentionally running without a bus, do not expose the model registry routes.
- Verify the bus connection (broker/socket) is created before routes are served.
- In tests, provide a real or mock event bus in the app state instead of `None`.
Example fix
// before
let Some(bus) = state.event_bus.clone() else {
return Err(GatewayError::Internal(anyhow::anyhow!(
"gateway is not wired to a live event bus; model registry unavailable"
)));
};
// after
let Some(bus) = state.event_bus.clone() else {
tracing::error!("event bus missing from app state; check startup wiring");
return Err(GatewayError::ServiceUnavailable(
"model registry unavailable: event bus not configured".into(),
));
}; Defensive patterns
Strategy: validation
Validate before calling
pub fn registry_available(state: &AppState) -> bool {
state.event_bus.is_some()
}
// gate the routes at router-build time
if !registry_available(&state) { skip_model_routes(); } Type guard
fn has_event_bus(state: &AppState) -> bool {
matches!(state.event_bus, Some(_))
} Try / catch
match list_models(&state, caller).await {
Err(e) if e.message().contains("not wired to a live event bus") => {
tracing::error!("event bus missing; model registry disabled");
StatusCode::SERVICE_UNAVAILABLE
}
r => r,
} Prevention
- Fail gateway startup fast if the event bus cannot be initialized rather than leaving it None.
- Only mount model registry routes when the bus is present.
- Add a boot-time assertion/log that event_bus was wired.
- In tests, always construct AppState with a bus (real or mock).
When it happens
Trigger: Calling any model registry endpoint (list models, get/set active model) on a gateway instance constructed without an event bus — e.g. a test/standalone build or a config path where the bus was never attached to state.
Common situations: Gateway started with event-bus wiring disabled or misconfigured; running a slim/CLI mode that never constructs the bus; tests using a stub state without `event_bus`; initialization order bug where the bus failed to start and was left `None`.
Related errors
- gateway is not wired to a live event bus; agent approval una
- registry reply was not an IPC message
- gateway is not wired to a live audit log; historical-query u
- gateway is not wired to a live event bus; audit stream unava
- registry reply not JSON: {e}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/90cfd88e7d4f2d2c.
Report an issue: GitHub.