embassy-rs/embassy · error

overflow when subtracting duration from instant

Error message

overflow when subtracting duration from instant

What it means

Instant - Duration arithmetic in embassy-time panics when the result underflows the tick representation (below the minimum representable instant). The Sub impl delegates to checked_sub and expects success, so underflow aborts the task. This prevents wrapped instants from corrupting elapsed/deadline calculations.

Solutions

  1. Use `Instant::checked_sub(duration)` and handle the None case instead of `-`
  2. Ensure the base instant is far enough in the future (e.g. `Instant::now()`) before subtracting
  3. Cap the Duration before subtracting: `duration.min(...)`

Example fix

// before
let start = deadline - lead_time; // panics on underflow
// after
let start = deadline.checked_sub(lead_time).unwrap_or(Instant::MIN);
Defensive patterns

Strategy: validation

Validate before calling

fn safe_sub(instant: Instant, d: Duration) -> Instant {
    instant.checked_sub(d).unwrap_or(Instant::MIN)
}

Prevention

When it happens

Trigger: Calling `instant - duration` (or `-=`, which routes through sub) where `instant.ticks - duration.ticks` drops below the minimum tick value — e.g. subtracting a large Duration from `Instant::MIN` or from an early/default-zero instant.

Common situations: Back-computing start times from deadlines with oversized durations, subtracting from a freshly created `Instant::from_secs(0)`-style value, or porting code that assumed wrapping arithmetic.

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/1746e8d68751a426. Report an issue: GitHub.

Appendix: source

Thrown at embassy-time/src/instant.rs:237

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

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

impl Sub<Instant> for Instant {
    type Output = Duration;

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

View on GitHub (pinned to 463a07b963)