astrid-runtime/astrid · error · GatewayError::Internal
gateway is not wired to a live kernel session; kernel…
Error message
gateway is not wired to a live kernel session; kernel requests unavailable
What it means
A kernel request was attempted with an event bus present but no kernel session id. BusKernelClient requires the session id to route requests to the kernel session, so kernel_client_for() returns GatewayError::Internal when session_id is None.
Solutions
- Complete the kernel session handshake and store the session id before serving kernel-backed routes
- Investigate startup errors from session registration and fix the root cause
- Gate routes on readiness so requests wait until state.session_id is Some
- Correct the state construction to pass the established session id
Example fix
// before let state = GatewayState::new(config, Some(event_bus), None)?; // after let session_id = handshake(&event_bus).await?; let state = GatewayState::new(config, Some(event_bus), Some(session_id))?;
Defensive patterns
Strategy: validation
Validate before calling
fn kernel_session_ready(state: &GatewayState) -> bool {
state.event_bus.is_some() && state.session_id.is_some()
} Type guard
fn session_id(state: &GatewayState) -> Option<SessionId> {
state.session_id.clone()
} Try / catch
if state.session_id.is_none() {
return Err(StatusCode::SERVICE_UNAVAILABLE);
}
let client = state.kernel_client_for(&caller)?; Prevention
- Establish and persist the kernel session id before serving kernel routes
- Alert on session registration failures during gateway startup
- Serialize request serving behind a readiness gate that requires session_id
When it happens
Trigger: Calling kernel_client_for() when event_bus is Some but session_id is None — typically a request racing the session handshake or a construction site that never stored the session id.
Common situations: Requests served before kernel session registration completes; failed/skipped session handshake in custom gateway embeddings; test setups wiring a bus but no session.
Related errors
- gateway is not wired to a live event bus; kernel requests…
- gateway is not wired to a live kernel session; admin…
- Astrid volume path has no file name
- authoritative principal store is unavailable
- cannot load capsule ' ' for unadmitted principal
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/a0918fd6e81c4ea3.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-gateway/src/state.rs:477
/// HTTP routes have already verified the bearer token and resolved the
/// caller/device scope. They should not re-enter the external socket
/// handshake, because the gateway intentionally does not possess arbitrary
/// agent private keys and would be downgraded to `anonymous`.
///
/// # Errors
/// Returns an internal error if the state was built without a live event
/// bus (the standalone tests-only constructor).
pub fn kernel_client_for(
&self,
caller: &crate::auth::CallerContext,
) -> Result<crate::bus_kernel::BusKernelClient, 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; kernel requests 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; kernel requests unavailable"
))
})?;
Ok(
crate::bus_kernel::BusKernelClient::new(bus, caller.principal.clone(), session_id.0)
.with_device_key_id(caller.device_key_id.clone()),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rate_limiter_blocks_within_window() {
let mut limiter = RedeemRateLimiter::default();
let ip: IpAddr = "127.0.0.1".parse().unwrap();View on GitHub (pinned to affd8760f4)