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

  1. Use `Instant::checked_add(duration)` and handle the None case instead of `+`
  2. Use `Instant::now() + duration` with a bounded/saturated duration (cap via `duration.min(Duration::from_secs(...))`)
  3. 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

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


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)