embassy-rs/embassy · error

overflow when subtracting durations

Error message

overflow when subtracting durations

What it means

embassy-time's `Duration` implements `Sub` via `checked_sub`; subtracting a larger duration from a smaller one (which would go negative) or overflowing the representation triggers `.expect("overflow when subtracting durations")` and panics. Durations are unsigned, so negative results are impossible to represent.

Solutions

  1. Compute elapsed as the larger minus the smaller, or use `saturating_sub` equivalent: `a.checked_sub(b).unwrap_or(Duration::from_secs(0))`
  2. Guard before subtracting: `if now < deadline { deadline - now } else { Duration::ZERO }`
  3. Reorder logic to compare first rather than subtract blindly

Example fix

// before
let remaining = deadline - now; // panics if now > deadline
// after
let remaining = if now > deadline { Duration::from_secs(0) } else { deadline - now };
Defensive patterns

Strategy: validation

Validate before calling

fn safe_sub(a: embassy_time::Duration, b: embassy_time::Duration) -> embassy_time::Duration {
    a.checked_sub(b).unwrap_or(embassy_time::Duration::from_secs(0))
}

Try / catch

// Underflow panic is not catchable in embedded; guard first:
let remaining = if now >= deadline { Duration::ZERO } else { deadline - now };

Prevention

When it happens

Trigger: `a - b` where `b > a` (would underflow below zero), e.g. computing elapsed time as `deadline - now` after the deadline has passed.

Common situations: Deadline/timeout math where `now` is compared after expiry; measuring elapsed time with reversed operand order; clock jitter causing `now` to exceed the stored deadline.

Related errors


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

Appendix: source

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

    ///
    /// ## 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)
    ///
    /// ## Panics
    ///
    /// Panics if the computed duration overflows.
    fn sub(self, rhs: Duration) -> Duration {
        self.checked_sub(rhs).expect("overflow when subtracting durations")
    }
}

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

impl Mul<u32> for Duration {
    type Output = Duration;

    /// Computes `Duration * u32`. [Read more](Mul)

View on GitHub (pinned to 463a07b963)