embassy-rs/embassy · error

overflow when adding durations

Error message

overflow when adding durations

What it means

embassy-time's `Duration` implements `Add` via `checked_add`; if the resulting tick count exceeds the internal representation (i64 microseconds / u64 ticks), `.expect("overflow when adding durations")` panics. It matches std's documented behavior that `Duration + Duration` panics on overflow.

Solutions

  1. Use `checked_add` and handle `None` yourself (clamp to `Duration::MAX` or return an error)
  2. Clamp inputs: `a.saturating_add(b)` if available, or `a.checked_add(b).unwrap_or(Duration::MAX)`
  3. Validate user-supplied timeout magnitudes before arithmetic

Example fix

// before
let total = a + b; // panics on overflow
// after
let total = a.checked_add(b).unwrap_or(Duration::MAX);
Defensive patterns

Strategy: try-catch

Validate before calling

fn safe_add(a: embassy_time::Duration, b: embassy_time::Duration) -> embassy_time::Duration {
    a.checked_add(b).unwrap_or(embassy_time::Duration::MAX)
}

Try / catch

// Rust panics are not catchable in embedded; use checked API instead:
let total = match a.checked_add(b) {
    Some(t) => t,
    None => Duration::MAX, // or return Err
};

Prevention

When it happens

Trigger: `a + b` where the combined tick count exceeds `Duration`'s maximum (e.g. adding two near-max durations, or accumulating durations in a loop without saturation).

Common situations: Computing deadlines from very large timeouts; summing user-provided durations; arithmetic on `Duration::MAX`; integer unit confusion (seconds vs micros) inflating values.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/2cbbda9028282b8b. Report an issue: GitHub.

Appendix: source

Thrown at embassy-time/src/duration.rs:216

        self.ticks.checked_mul(rhs as _).map(|ticks| Duration { ticks })
    }

    /// Divides one `Duration` by a scalar `u32`, returning a new `Duration` or `None` in the event of an overflow.
    pub fn checked_div(self, rhs: u32) -> Option<Duration> {
        self.ticks.checked_div(rhs as _).map(|ticks| Duration { ticks })
    }
}

impl Add for Duration {
    type Output = Duration;

    /// Computes `Duration + Duration`. [Read more](Add)
    ///
    /// ## Panics
    ///
    /// Panics if the computed duration overflows.
    fn add(self, rhs: Duration) -> Duration {
        self.checked_add(rhs).expect("overflow when adding durations")
    }
}

impl AddAssign for Duration {
    /// Computes `Duration += Duration`. [Read more](AddAssign)
    ///
    /// ## Panics
    ///
    /// Panics if the computed duration overflows.
    fn add_assign(&mut self, rhs: Duration) {
        *self = *self + rhs;
    }
}

impl Sub for Duration {
    type Output = Duration;

    /// Computes `Duration - Duration`. [Read more](Sub)

View on GitHub (pinned to 463a07b963)