{"record":{"id":"105dddd660b31ffc","repo":"FuelLabs/fuel-core","slug":"relayer-is-too-far-out-of-sync","errorCode":null,"errorMessage":"Relayer is too far out of sync","messagePattern":"Relayer is too far out of sync","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/fuel-core/src/service/adapters/consensus_module.rs","lineNumber":72,"sourceCode":"    }\n\n    fn block_header_merkle_root(&self, height: &BlockHeight) -> StorageResult<Bytes32> {\n        self.storage::<FuelBlocks>().root(height).map(Into::into)\n    }\n}\n\n#[async_trait::async_trait]\nimpl RelayerPort for MaybeRelayerAdapter {\n    async fn await_until_if_in_range(\n        &self,\n        da_height: &DaBlockHeight,\n        _max_da_lag: &DaBlockHeight,\n    ) -> anyhow::Result<()> {\n        #[cfg(feature = \"relayer\")]\n        {\n            if let Some(sync) = &self.relayer_synced {\n                let current_height = sync.get_finalized_da_height();\n                anyhow::ensure!(\n                    da_height.saturating_sub(*current_height) <= **_max_da_lag,\n                    \"Relayer is too far out of sync\"\n                );\n                sync.await_at_least_synced(da_height).await?;\n            }\n            Ok(())\n        }\n        #[cfg(not(feature = \"relayer\"))]\n        {\n            anyhow::ensure!(\n                **da_height == 0,\n                \"Cannot have a da height above zero without a relayer\"\n            );\n            Ok(())\n        }\n    }\n}\n","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/b9d4d170da3a31c9ace5f963d633b326348e0d42/crates/fuel-core/src/service/adapters/consensus_module.rs#L54-L90","documentation":"Thrown by MaybeRelayerAdapter::await_until_if_in_range (crates/fuel-core/src/service/adapters/consensus_module.rs:72), the RelayerPort used during block production/import when the relayer feature is enabled. It computes da_height - relayer_finalized_da_height and requires the gap to stay within max_da_lag; a larger gap fails fast instead of waiting on await_at_least_synced, because the relayer may never reach the requested DA height.","triggerScenarios":"Producing or importing a block whose header da_height exceeds sync.get_finalized_da_height() by more than the max_da_lag passed by the PoA consensus module.","commonSituations":"Relayer lagging due to a slow or rate-limited Ethereum RPC endpoint; freshly started relayer syncing the DA chain from the beginning; a manually crafted or test-produced block with an inflated da_height; max_da_lag left at a small default in the consensus config.","solutions":["Wait for the relayer to catch up (watch its sync logs/metrics) and let block production retry","Point the node at a faster, reliable Ethereum RPC endpoint for the relayer","Increase max_da_lag in the PoA consensus config if a larger, controlled DA lag is acceptable","If the block's da_height came from custom producer/test code, clamp it to a realistic finalized DA height"],"exampleFix":"// before (custom block production):\n//   header.set_da_height(DaBlockHeight(15_000_000)); // eth mainnet tip\n// after:\n//   let finalized = relayer.get_finalized_da_height();\n//   header.set_da_height(finalized + DaBlockHeight(1));","handlingStrategy":"retry","validationCode":"// before triggering production for a da_height:\nlet finalized = relayer_sync.get_finalized_da_height();\nlet lag = da_height.saturating_sub(finalized);\nif lag > max_da_lag {\n    // wait/retry later instead of calling into production now\n}","typeGuard":null,"tryCatchPattern":"loop {\n    match relayer_port.await_until_if_in_range(&da_height, &max_da_lag).await {\n        Err(e) if e.to_string().contains(\"too far out of sync\") => {\n            tokio::time::sleep(Duration::from_secs(10)).await; // relayer still catching up\n        }\n        other => break other,\n    }\n}","preventionTips":["Run the relayer against a low-latency, non-rate-limited Ethereum endpoint","Size max_da_lag to the worst expected relayer catch-up time during block production","Alert on relayer finalized-height lag so you fix sync before block production fails"],"tags":["fuel-core","relayer","da-height","consensus","sync"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}