{"record":{"id":"1e48f67250b3732f","repo":"linera-io/linera-protocol","slug":"http-server-exited-unexpectedly-result","errorCode":null,"errorMessage":"HTTP server exited unexpectedly: {result:?}","messagePattern":"HTTP server exited unexpectedly: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"linera-bridge/src/relay/mod.rs","lineNumber":517,"sourceCode":"\n    // ── Main loop: process chain operations + notifications ──\n    tracing::info!(\"Listening for chain operations and notifications...\");\n    loop {\n        tokio::select! {\n            result = &mut chain_listener_handle => {\n                anyhow::bail!(\"Chain listener exited unexpectedly: {result:?}\");\n            }\n            result = &mut evm_scan_handle => {\n                anyhow::bail!(\"EVM scan loop exited unexpectedly: {result:?}\");\n            }\n            result = &mut linera_scan_handle => {\n                anyhow::bail!(\"Linera scan loop exited unexpectedly: {result:?}\");\n            }\n            result = &mut retry_handle => {\n                anyhow::bail!(\"Retry loop exited unexpectedly: {result:?}\");\n            }\n            result = &mut http_server_handle => {\n                anyhow::bail!(\"HTTP server exited unexpectedly: {result:?}\");\n            }\n            result = &mut admin_server_handle => {\n                anyhow::bail!(\"Admin HTTP server exited unexpectedly: {result:?}\");\n            }\n            _ = inbox_drain_interval.tick() => {\n                // Periodic safety net for a missed `NewIncomingBundle`: sync and\n                // drain the inbox so stranded messages (e.g. user burns) are\n                // eventually processed even without a fresh notification.\n                if let Err(e) = chain_client.synchronize_from_validators().await {\n                    tracing::warn!(\"Periodic sync before inbox drain failed: {e}\");\n                } else {\n                    match chain_client.process_inbox().await {\n                        Ok((certs, _)) if !certs.is_empty() => {\n                            tracing::info!(count = certs.len(), \"Periodic inbox drain processed messages\");\n                        }\n                        Ok(_) => {}\n                        Err(e) => tracing::warn!(\"Periodic inbox drain failed: {e}\"),\n                    }","sourceCodeStart":499,"sourceCodeEnd":535,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-bridge/src/relay/mod.rs#L499-L535","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check logs for \"HTTP server error\" — the context around the serve error names the io failure.","If a request triggered a panic, correlate with access logs and fix the handler (guard the failing input).","Verify nothing else is disrupting the bound port (another process rebinding, firewall/iptables flush in containers).","Restart the relay under a supervisor; startup will fail loudly if the port is genuinely taken."],"exampleFix":"// before\nresult = &mut http_server_handle => {\n    anyhow::bail!(\"HTTP server exited unexpectedly: {result:?}\");\n}\n\n// after: unwrap the JoinError to keep the io error chain\nresult = &mut http_server_handle => {\n    let inner = result.unwrap_or_else(|join| Err(anyhow::anyhow!(\"join error: {join}\")));\n    anyhow::bail!(\"HTTP server exited unexpectedly: {inner:?}\");\n}","handlingStrategy":"retry","validationCode":"// Before serve_loop, the listener bind already fails fast on port conflict;\n// keep an exclusive claim on the port (single relay instance per host:port).","typeGuard":null,"tryCatchPattern":"// Fatal by design; restart the process. Surface the inner io error from the JoinError:\nif let Err(join) = &result { tracing::error!(\"HTTP server join error: {join}\"); }","preventionTips":["One process per listening port; use socket activation or reserved ports in containers.","Panic-catch in HTTP handlers (tower catch_panic layer) so no single request can kill the server task."],"tags":["linera-bridge","relay","http-server","axum","task-supervision","tokio","rust"],"backgroundTag":"background-task-exited","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}