{"record":{"id":"c0cd4bb028a255c8","repo":"linera-io/linera-protocol","slug":"retry-loop-exited-unexpectedly-result","errorCode":null,"errorMessage":"Retry loop exited unexpectedly: {result:?}","messagePattern":"Retry loop exited unexpectedly: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"linera-bridge/src/relay/mod.rs","lineNumber":514,"sourceCode":"    let mut inbox_drain_interval = tokio::time::interval(monitor_scan_interval);\n    // Consume the immediate first tick — the startup drain above already ran.\n    inbox_drain_interval.tick().await;\n\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                        }","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-bridge/src/relay/mod.rs#L496-L532","documentation":"In serve_loop's tokio::select!, the retry loop task exited. This loop re-drives previously failed operations (e.g. settlements that timed out or reverted) on a schedule; its unexpected exit — error or panic — fails the whole relay because failed operations would never be retried.","triggerScenarios":"The retry future returns Err (persistent failure re-loading or re-executing the retry queue, e.g. storage/RPC errors that outlive its internal handling) or panics while re-running an operation such as re-sending a settlement transaction.","commonSituations":"Both EVM and retry paths hitting the same broken RPC for long stretches; a retry entry whose replay panics due to ABI/state drift after a contract upgrade; storage backing the retry queue becoming unavailable.","solutions":["Find the retry loop's last logged error before this bail — it names the operation and underlying failure.","Fix that underlying cause (RPC availability, contract state drift, storage), then restart the relay; the retry queue is reprocessed from persisted state.","If a specific poisoned retry entry panics repeatedly, remove/resolve that entry (e.g. mark the deposit as failed manually) after root-causing.","Supervise the relay process for automatic restart."],"exampleFix":"// before\nresult = &mut retry_handle => {\n    anyhow::bail!(\"Retry loop exited unexpectedly: {result:?}\");\n}\n\n// after: propagate the inner error chain instead of only Debug-printing it\nresult = &mut retry_handle => {\n    anyhow::bail!(\"Retry loop exited unexpectedly: {result:?}; \\\n                 inspect preceding retry-loop error logs to identify the poisoned operation\");\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Fatal by design; supervisor restart reprocesses the persisted retry queue.\n// On repeated crashes, inspect the retry queue for a poisoned entry and resolve it manually.","preventionTips":["Make retry re-execution idempotent so restarts are safe.","Bound per-entry retry attempts and move permanently-failing entries to a dead-letter log instead of looping forever."],"tags":["linera-bridge","relay","retry","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"}