{"record":{"id":"d81020a1688149ff","repo":"embassy-rs/embassy","slug":"overflow-when-subtracting-durations","errorCode":null,"errorMessage":"overflow when subtracting durations","messagePattern":"overflow when subtracting durations","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-time/src/duration.rs","lineNumber":240,"sourceCode":"    ///\n    /// ## Panics\n    ///\n    /// Panics if the computed duration overflows.\n    fn add_assign(&mut self, rhs: Duration) {\n        *self = *self + rhs;\n    }\n}\n\nimpl Sub for Duration {\n    type Output = Duration;\n\n    /// Computes `Duration - Duration`. [Read more](Sub)\n    ///\n    /// ## Panics\n    ///\n    /// Panics if the computed duration overflows.\n    fn sub(self, rhs: Duration) -> Duration {\n        self.checked_sub(rhs).expect(\"overflow when subtracting durations\")\n    }\n}\n\nimpl SubAssign for Duration {\n    /// Computes `Duration -= Duration`. [Read more](SubAssign)\n    ///\n    /// ## Panics\n    ///\n    /// Panics if the computed duration overflows.\n    fn sub_assign(&mut self, rhs: Duration) {\n        *self = *self - rhs;\n    }\n}\n\nimpl Mul<u32> for Duration {\n    type Output = Duration;\n\n    /// Computes `Duration * u32`. [Read more](Mul)","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-time/src/duration.rs#L222-L258","documentation":"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.","triggerScenarios":"`a - b` where `b > a` (would underflow below zero), e.g. computing elapsed time as `deadline - now` after the deadline has passed.","commonSituations":"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.","solutions":["Compute elapsed as the larger minus the smaller, or use `saturating_sub` equivalent: `a.checked_sub(b).unwrap_or(Duration::from_secs(0))`","Guard before subtracting: `if now < deadline { deadline - now } else { Duration::ZERO }`","Reorder logic to compare first rather than subtract blindly"],"exampleFix":"// before\nlet remaining = deadline - now; // panics if now > deadline\n// after\nlet remaining = if now > deadline { Duration::from_secs(0) } else { deadline - now };","handlingStrategy":"validation","validationCode":"fn safe_sub(a: embassy_time::Duration, b: embassy_time::Duration) -> embassy_time::Duration {\n    a.checked_sub(b).unwrap_or(embassy_time::Duration::from_secs(0))\n}","typeGuard":null,"tryCatchPattern":"// Underflow panic is not catchable in embedded; guard first:\nlet remaining = if now >= deadline { Duration::ZERO } else { deadline - now };","preventionTips":["Order operands so the minuend is always >= the subtrahend","Use checked_sub for deadline/now arithmetic","Compare durations before computing differences"],"tags":["arithmetic","duration","underflow","panic"],"backgroundTag":"arithmetic-overflow","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}