embassy-rs/embassy · error
overflow when adding duration to instant
Error message
overflow when adding duration to instant
What it means
Instant + Duration arithmetic in embassy-time panics when the resulting Instant tick value overflows the underlying 64-bit tick representation. The Add impl delegates to checked_add and expects success, so any overflowing addition aborts the task. This guards against silently wrapping instants, which would corrupt all timeout/scheduling math.
Solutions
- Use `Instant::checked_add(duration)` and handle the None case instead of `+`
- Use `Instant::now() + duration` with a bounded/saturated duration (cap via `duration.min(Duration::from_secs(...))`)
- Verify the Duration constant is expressed in the intended unit (ticks vs micros) before adding
Example fix
// before let deadline = start + user_duration; // panics on overflow // after let deadline = start.checked_add(user_duration).unwrap_or(Instant::MAX);
Defensive patterns
Strategy: validation
Validate before calling
fn safe_add(instant: Instant, d: Duration) -> Instant {
instant.checked_add(d).unwrap_or(Instant::MAX)
} Prevention
- Always prefer checked_add/checked_sub for Instant arithmetic with dynamic durations
- Clamp externally sourced Durations to a sane maximum before use
- Add unit tests with Duration::MAX to catch overflow paths
When it happens
Trigger: Calling `instant + duration` (or `+=`, which routes through add) where `instant.ticks + duration.ticks` exceeds i64::MAX ticks — e.g. adding huge Durations like `Duration::from_secs(u64::MAX)` or repeated additions from a large base instant.
Common situations: Computing deadlines with unvalidated user-supplied durations, accumulating timeouts in a loop without saturation, or migrating from libraries where Duration was larger/smaller scale so old constants now overflow.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- overflow when subtracting duration from instant
- QSPI address too large to be represented with the given…
- Can only take the executor once
- Invalid FilterConfig (TooManyFilters)! A FilterConfig must…
- Invalid FilterConfig (EmptyFilterConfig)! A FilterConfig…
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/c822c28d84664306.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-time/src/instant.rs:212
/// Subtracts a Duration from self. In case of overflow, the minimum value is returned.
#[inline]
pub const fn saturating_sub(mut self, duration: Duration) -> Self {
self.ticks = self.ticks.saturating_sub(duration.ticks);
self
}
}
impl Add<Duration> for Instant {
type Output = Instant;
/// Computes `Instant + Duration`. [Read more](Add)
///
/// ## Panics
///
/// Panics if the computed instant overflows.
fn add(self, other: Duration) -> Instant {
self.checked_add(other)
.expect("overflow when adding duration to instant")
}
}
impl AddAssign<Duration> for Instant {
/// Computes `Instant += Duration`. [Read more](AddAssign)
///
/// ## Panics
///
/// Panics if the computed instant overflows.
fn add_assign(&mut self, other: Duration) {
*self = *self + other;
}
}
impl Sub<Duration> for Instant {
type Output = Instant;
/// Computes `Instant - Duration`. [Read more](Sub)View on GitHub (pinned to 463a07b963)