FuelLabs/fuel-core · error
Time exceeds system limits
Error message
Time exceeds system limits
What it means
In the main task loop, Trigger::Interval computes the next wake-up as self.last_block_created.checked_add(block_time) on tokio::time::Instant. If that addition overflows the platform Instant range, the error is wrapped in TaskNextAction::ErrorContinue: the service logs it and retries the same computation, so with a too-large block_time the node never schedules another block and stalls. This is a config-sanity failure, not an organic runtime condition.
Source
Thrown at crates/services/consensus_module/poa/src/service.rs:763
return action;
}
if let Some(action) = self.maybe_produce_predefined_block().await {
tracing::debug!("Predefined block produced, stopping PoA task");
return action;
}
let next_block_production: BoxFuture<Instant> = match self.trigger {
Trigger::Never => Box::pin(core::future::pending::<Instant>()),
Trigger::Instant => Box::pin(async {
let _ = self.new_txs_watcher.changed().await;
Instant::now()
}),
Trigger::Interval { block_time } => {
let next_block_time = match self
.last_block_created
.checked_add(block_time)
.ok_or(anyhow!("Time exceeds system limits"))
{
Ok(time) => time,
Err(err) => return TaskNextAction::ErrorContinue(err),
};
Box::pin(async move {
sleep_until(next_block_time).await;
Instant::now()
})
}
Trigger::Open { period } => {
let deadline = match self
.last_block_created
.checked_add(period)
.ok_or(anyhow!("Time exceeds system limits"))
{
Ok(time) => time,
Err(err) => return TaskNextAction::ErrorContinue(err),
};View on GitHub (pinned to b9d4d170da)
Solutions
- Set a sane block_time (e.g. 1s–60s: Duration::from_secs(5)) in the PoA trigger config.
- Validate trigger intervals at startup (Instant::now().checked_add(step) must be Some) and fail fast with a clear config error.
- Restart the node after fixing the config — the ErrorContinue loop does not self-heal while the misconfigured interval remains.
Example fix
// before
trigger: Trigger::Interval { block_time: Duration::MAX }
// after
trigger: Trigger::Interval { block_time: Duration::from_secs(5) } Defensive patterns
Strategy: validation
Validate before calling
// Validate the trigger before constructing/starting the service
fn validate_trigger_scheduling(trigger: &fuel_core_poa::Trigger) -> anyhow::Result<()> {
let now = tokio::time::Instant::now();
let step = match trigger {
fuel_core_poa::Trigger::Interval { block_time } => *block_time,
fuel_core_poa::Trigger::Open { period } => *period,
_ => return Ok(()),
};
anyhow::ensure!(
now.checked_add(step).is_some(),
"trigger interval {step:?} overflows the Instant range"
);
Ok(())
} Prevention
- Bound-check every Duration read from config files before converting it into a Trigger variant.
- Standardize on human-scale intervals (seconds) and reject values above, e.g., one hour for block_time.
- Watch node logs for repeated ErrorContinue entries after trigger config changes; they indicate a stalled scheduler, not transient noise.
When it happens
Trigger: Config.trigger = Trigger::Interval { block_time } with a block_time so large that Instant + block_time overflows (e.g. Duration::MAX, or a units mistake such as passing seconds where millis were intended, or an unclamped u64 from a config file).
Common situations: Copy-pasted/mis-edited TOML config values for block_time; config generators emitting raw integers without bounds; unit confusion between seconds and milliseconds when building Duration.
Related errors
- The provided time parameters lead to an overflow
- Manual block production is not allowed with trigger `Open`
- unable to produce blocks without a consensus key
- Block production timed out
- The block timestamp should monotonically increase
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/c84d33e1b4095467.
Report an issue: GitHub.