{"record":{"id":"e726309bcb275c21","repo":"FuelLabs/fuel-core","slug":"publish-abandoned-quorum-reached-before-this-node-e72630","errorCode":null,"errorMessage":"publish abandoned: quorum reached before this node responded (background task still running)","messagePattern":"publish abandoned: quorum reached before this node responded \\(background task still running\\)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/fuel-core/src/service/adapters/consensus_module/poa.rs","lineNumber":1209,"sourceCode":"            if self.quorum_reached(written_count) {\n                poa_metrics().observe_quorum_latency(\n                    QuorumOp::Publish,\n                    quorum_start.elapsed().as_secs_f64(),\n                );\n                // Short-circuit: stop draining, but leave the remaining\n                // tasks running. They will each complete their write\n                // attempt; when `rx` drops below, their subsequent sends\n                // become no-ops, but the publish has landed on the node.\n                break;\n            }\n        }\n        drop(rx);\n\n        results\n            .into_iter()\n            .map(|r| {\n                r.unwrap_or_else(|| {\n                    Err(anyhow!(\n                        \"publish abandoned: quorum reached before this \\\n                         node responded (background task still running)\"\n                    ))\n                })\n            })\n            .collect()\n    }\n\n    /// Repropose a sub-quorum block to all Redis nodes to reach quorum.\n    /// Called during reconciliation when a block exists on some nodes but\n    /// below quorum — possibly from a leader that published and committed\n    /// locally but whose write only reached a subset of nodes.\n    ///\n    /// `pre_existing_count` is the number of nodes already confirmed to\n    /// have this specific block during the reconciliation read phase.\n    ///\n    /// Uses `publish_block_on_all_nodes` which runs `write_block.lua`:\n    /// - Written: node accepted the block (counted toward quorum)","sourceCodeStart":1191,"sourceCodeEnd":1227,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/add100d30d21498e8528c46be8567fbd2ea019af/crates/fuel-core/src/service/adapters/consensus_module/poa.rs#L1191-L1227","documentation":"Informational short-circuit in publish_block_on_all_nodes: while draining per-node write results, quorum_reached(written_count) became true before every Redis node had reported. The loop breaks early instead of waiting for the remaining writes; the straggler tokio tasks keep running in the background and their channel sends become no-ops once rx is dropped. It fires on the happy path whenever quorum lands before the slowest nodes respond, not on a write failure.","triggerScenarios":"Thrown at crates/fuel-core/src/service/adapters/consensus_module/poa.rs:1209 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Treat as expected behavior: quorum semantics allow ignoring slow minority nodes","Ensure the spawned tasks hold an Arc to the block payload so background completion is safe and allocation-free","Observe quorum latency metrics already emitted here to detect chronically slow nodes","If background task leakage matters, add a JoinHandle abort or a completion deadline after quorum is reached"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"add100d30d21498e8528c46be8567fbd2ea019af","analyzedAt":"2026-09-05T18:46:12.018Z","contentChangedAt":"2026-09-05T18:46:12.018Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}