linera-io/linera-protocol · critical

HTTP server exited unexpectedly: {result:?}

Error message

HTTP server exited unexpectedly: {result:?}

What it means

In serve_loop's tokio::select!, the main HTTP server task (axum::serve) exited. The relay serves an HTTP API (health/metrics/operations); if that server task stops — bind errors surfacing at serve time, a fatal connection handler error, or task abort — the relay treats it as fatal and shuts down all loops.

Source

Thrown at linera-bridge/src/relay/mod.rs:517

    // ── Main loop: process chain operations + notifications ──
    tracing::info!("Listening for chain operations and notifications...");
    loop {
        tokio::select! {
            result = &mut chain_listener_handle => {
                anyhow::bail!("Chain listener exited unexpectedly: {result:?}");
            }
            result = &mut evm_scan_handle => {
                anyhow::bail!("EVM scan loop exited unexpectedly: {result:?}");
            }
            result = &mut linera_scan_handle => {
                anyhow::bail!("Linera scan loop exited unexpectedly: {result:?}");
            }
            result = &mut retry_handle => {
                anyhow::bail!("Retry loop exited unexpectedly: {result:?}");
            }
            result = &mut http_server_handle => {
                anyhow::bail!("HTTP server exited unexpectedly: {result:?}");
            }
            result = &mut admin_server_handle => {
                anyhow::bail!("Admin HTTP server exited unexpectedly: {result:?}");
            }
            _ = inbox_drain_interval.tick() => {
                // Periodic safety net for a missed `NewIncomingBundle`: sync and
                // drain the inbox so stranded messages (e.g. user burns) are
                // eventually processed even without a fresh notification.
                if let Err(e) = chain_client.synchronize_from_validators().await {
                    tracing::warn!("Periodic sync before inbox drain failed: {e}");
                } else {
                    match chain_client.process_inbox().await {
                        Ok((certs, _)) if !certs.is_empty() => {
                            tracing::info!(count = certs.len(), "Periodic inbox drain processed messages");
                        }
                        Ok(_) => {}
                        Err(e) => tracing::warn!("Periodic inbox drain failed: {e}"),
                    }

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Check logs for "HTTP server error" — the context around the serve error names the io failure.
  2. If a request triggered a panic, correlate with access logs and fix the handler (guard the failing input).
  3. Verify nothing else is disrupting the bound port (another process rebinding, firewall/iptables flush in containers).
  4. Restart the relay under a supervisor; startup will fail loudly if the port is genuinely taken.

Example fix

// before
result = &mut http_server_handle => {
    anyhow::bail!("HTTP server exited unexpectedly: {result:?}");
}

// after: unwrap the JoinError to keep the io error chain
result = &mut http_server_handle => {
    let inner = result.unwrap_or_else(|join| Err(anyhow::anyhow!("join error: {join}")));
    anyhow::bail!("HTTP server exited unexpectedly: {inner:?}");
}
Defensive patterns

Strategy: retry

Validate before calling

// Before serve_loop, the listener bind already fails fast on port conflict;
// keep an exclusive claim on the port (single relay instance per host:port).

Try / catch

// Fatal by design; restart the process. Surface the inner io error from the JoinError:
if let Err(join) = &result { tracing::error!("HTTP server join error: {join}"); }

Prevention

When it happens

Trigger: The axum server future returns Err (its .context("HTTP server error") result), e.g. the listener socket failing at runtime, or the task panics inside a tower/axum layer. Port conflicts usually fail at bind (before serve_loop), so runtime exit here is typically socket/handler level.

Common situations: The listening socket being closed or reset externally (container networking changes, OOM killing connections); a panic in an HTTP handler or middleware triggered by a specific request; extremely rare axum internal errors.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/1e48f67250b3732f. Report an issue: GitHub.