astrid-runtime/astrid · error · GatewayError::Internal
gateway is not wired to a live audit log; historical-query u
Error message
gateway is not wired to a live audit log; historical-query unavailable
What it means
The historical audit-query endpoint returns this Internal (500) error when either state.audit_log or state.session_id is None. Both must be present because the handler reads entries for the caller's session from the audit log; a gateway started without an audit log (or without a session id) cannot serve historical queries.
Source
Thrown at crates/astrid-gateway/src/routes/audit.rs:215
)
)]
pub async fn get_audit(
State(state): State<Arc<GatewayState>>,
Query(query): Query<AuditQuery>,
req: Request<axum::body::Body>,
) -> GatewayResult<Json<AuditQueryResponse>> {
let caller = caller_from(&req)?;
let capability_probe = req
.extensions()
.get::<super::events::CapabilityProbe>()
.cloned()
.unwrap_or_else(super::events::CapabilityProbe::deny_all);
let caller_principal = caller.principal.clone();
let (audit_log, session_id) = match (state.audit_log.as_ref(), state.session_id.as_ref()) {
(Some(log), Some(sid)) => (log.clone(), sid.clone()),
_ => {
return Err(GatewayError::Internal(anyhow::anyhow!(
"gateway is not wired to a live audit log; historical-query unavailable"
)));
},
};
let limit = match query.limit {
Some(l) if l > MAX_LIMIT => {
return Err(GatewayError::BadRequest(format!(
"limit {l} exceeds the cap of {MAX_LIMIT}"
)));
},
Some(0) | None => DEFAULT_LIMIT,
Some(l) => l,
};
// Pull the full session slice from the audit log. The audit log
// doesn't expose an "after cursor" query primitive today, so we
// fetch + filter + paginate in-process. The persistent log onView on GitHub (pinned to affd8760f4)
Solutions
- Start the gateway with a live audit log wired into GatewayState (audit_log: Some(...)).
- Ensure session_id is set on GatewayState before serving traffic.
- Fix any audit-backend initialization failure that left audit_log as None, then restart.
- Don't expose the /api/audit route on deployments that intentionally run without an audit log.
Example fix
// before
let state = GatewayState { audit_log: None, session_id: None, .. };
// after
let audit = RotatingAuditLog::open(&config.audit_path).await?;
let state = GatewayState { audit_log: Some(Arc::new(audit)), session_id: Some(session_id), .. }; Defensive patterns
Strategy: fallback
Validate before calling
// check audit capability before querying
const cap = await fetch('/api/audit/_capability');
if (!cap.ok) return []; // historical query unsupported on this node Type guard
fn audit_available(state: &GatewayState) -> bool {
state.audit_log.is_some() && state.session_id.is_some()
} Try / catch
try {
const entries = await fetch('/api/audit?limit=100');
} catch (e) {
if (/historical-query unavailable/.test(e.message)) return []; // no audit backend on this node
throw e;
} Prevention
- Run gateways with a configured audit log if audit history is needed.
- Monitor startup logs for audit-log initialization failures and alert.
- Return empty/degraded results rather than hard-failing UIs when audit is disabled.
When it happens
Trigger: GET /api/audit (get_audit) on a gateway where audit_log or session_id in GatewayState is None — i.e. the server was built without a live audit log or session identity.
Common situations: Gateway launched in a mode that disables audit logging; audit backend failed to open at startup so audit_log stayed None; querying audit history on a freshly restarted node whose session_id hasn't been established.
Related errors
- gateway is not wired to a live event bus; agent approval una
- lifecycle manifest declares environment state but no durable
- no corpus selected; omit --no-synthetic or pass a corpus or
- duplicate corpus label {:?}
- --git-history requires non-empty NAME=REPO::RELATIVE_PATH
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/853240c068fccece.
Report an issue: GitHub.