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
- Use `Instant::checked_sub(duration)` and handle the None case instead of `-`
- Ensure the base instant is far enough in the future (e.g. `Instant::now()`) before subtracting
- 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
- Base subtractions on Instant::now() rather than zero-valued instants
- Prefer computing deadlines forward (+) instead of backward (-) when possible
- Use checked_sub when the duration magnitude is untrusted
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
- overflow when adding duration to 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/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)