bevyengine/bevy · critical
overflow when adding duration to instant
Error message
overflow when adding duration to instant
What it means
bevy_platform's fallback `Instant` (no_std time) wraps a tick-count `Duration`. `impl Add<Duration> for Instant` uses `checked_add` and `.expect("overflow when adding duration to instant")` (crates/bevy_platform/src/time/fallback.rs:110), mirroring std's panic-on-overflow contract: if the resulting counter value cannot be represented, the add panics.
Source
Thrown at crates/bevy_platform/src/time/fallback.rs:110
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
/// otherwise.
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
self.0.checked_sub(duration).map(Instant)
}
}
impl Add<Duration> for Instant {
type Output = Instant;
/// # Panics
///
/// This function may panic if the resulting point in time cannot be represented by the
/// underlying data structure. See [`Instant::checked_add`] for a version without panic.
fn add(self, other: Duration) -> Instant {
self.checked_add(other)
.expect("overflow when adding duration to instant")
}
}
impl AddAssign<Duration> for Instant {
fn add_assign(&mut self, other: Duration) {
*self = *self + other;
}
}
impl Sub<Duration> for Instant {
type Output = Instant;
fn sub(self, other: Duration) -> Instant {
self.checked_sub(other)
.expect("overflow when subtracting duration from instant")
}
}
View on GitHub (pinned to 396ca72708)
Solutions
- Use `instant.checked_add(duration)` (or `saturating_add` where appropriate) instead of `+`
- Clamp durations from config/network before deadline math: `d.min(Duration::from_secs(86400))`
- Validate parsed timeout values at load time
Example fix
// before: panics if duration is huge let deadline = start + timeout; // after: handle the unrepresentable case let deadline = start.checked_add(timeout).unwrap_or_else(|| start + Duration::from_secs(3600));
Defensive patterns
Strategy: validation
Validate before calling
let deadline = start
.checked_add(timeout)
.ok_or(TimeoutTooLarge)?; // or clamp:
// let deadline = start.checked_add(timeout).unwrap_or(start + Duration::from_secs(3600)); Prevention
- Prefer checked_add/saturating_add in all deadline math
- Clamp timeouts parsed from config: d.min(Duration::from_secs(60 * 60 * 24))
- Unit-test clock math with Duration::MAX to catch panics before release
When it happens
Trigger: `instant + duration` where the sum overflows the internal u64 nanosecond counter — practically this needs a Duration near `u64::MAX` nanoseconds (~584 years), e.g. `Instant::now() + Duration::MAX`, a `from_secs(u64::MAX)` from misparsed config, or saturated duration accumulation in a timer loop.
Common situations: Timeout/deadline math built from unchecked config values; `saturating_add`ed durations accumulating over long runs; unit tests using absurd durations against the fallback clock.
Related errors
- overflow when subtracting duration from instant
- An elapsed time getter has not been provided to `Instant`. P
- array layout should be valid
- The TimeSender channel should always be empty during render.
- Cannot call `ReflectComponent::reflect_mut` on component {na
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/c7e80ce066ec7ddb.
Report an issue: GitHub.