FuelLabs/fuel-core · error · anyhow::Error
Relayer is too far out of sync
Error message
Relayer is too far out of sync
What it means
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.
Source
Thrown at crates/fuel-core/src/service/adapters/consensus_module.rs:72
}
fn block_header_merkle_root(&self, height: &BlockHeight) -> StorageResult<Bytes32> {
self.storage::<FuelBlocks>().root(height).map(Into::into)
}
}
#[async_trait::async_trait]
impl RelayerPort for MaybeRelayerAdapter {
async fn await_until_if_in_range(
&self,
da_height: &DaBlockHeight,
_max_da_lag: &DaBlockHeight,
) -> anyhow::Result<()> {
#[cfg(feature = "relayer")]
{
if let Some(sync) = &self.relayer_synced {
let current_height = sync.get_finalized_da_height();
anyhow::ensure!(
da_height.saturating_sub(*current_height) <= **_max_da_lag,
"Relayer is too far out of sync"
);
sync.await_at_least_synced(da_height).await?;
}
Ok(())
}
#[cfg(not(feature = "relayer"))]
{
anyhow::ensure!(
**da_height == 0,
"Cannot have a da height above zero without a relayer"
);
Ok(())
}
}
}
View on GitHub (pinned to b9d4d170da)
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
Example fix
// before (custom block production): // header.set_da_height(DaBlockHeight(15_000_000)); // eth mainnet tip // after: // let finalized = relayer.get_finalized_da_height(); // header.set_da_height(finalized + DaBlockHeight(1));
Defensive patterns
Strategy: retry
Validate before calling
// before triggering production for a da_height:
let finalized = relayer_sync.get_finalized_da_height();
let lag = da_height.saturating_sub(finalized);
if lag > max_da_lag {
// wait/retry later instead of calling into production now
} Try / catch
loop {
match relayer_port.await_until_if_in_range(&da_height, &max_da_lag).await {
Err(e) if e.to_string().contains("too far out of sync") => {
tokio::time::sleep(Duration::from_secs(10)).await; // relayer still catching up
}
other => break other,
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Cannot have a da height above zero without a relayer
- relayer database height({relayer_db_height}) is less than ta
- The override height is zero. The override height should be g
- Cannot have a da height above zero without a relayer
- message da_height cannot be greater than genesis da block he
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/105dddd660b31ffc.
Report an issue: GitHub.