{"record":{"id":"1746e8d68751a426","repo":"embassy-rs/embassy","slug":"overflow-when-subtracting-duration-from-instant","errorCode":null,"errorMessage":"overflow when subtracting duration from instant","messagePattern":"overflow when subtracting duration from instant","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-time/src/instant.rs","lineNumber":237,"sourceCode":"    /// ## Panics\n    ///\n    /// Panics if the computed instant overflows.\n    fn add_assign(&mut self, other: Duration) {\n        *self = *self + other;\n    }\n}\n\nimpl Sub<Duration> for Instant {\n    type Output = Instant;\n\n    /// Computes `Instant - Duration`. [Read more](Sub)\n    ///\n    /// ## Panics\n    ///\n    /// Panics if the computed instant overflows.\n    fn sub(self, other: Duration) -> Instant {\n        self.checked_sub(other)\n            .expect(\"overflow when subtracting duration from instant\")\n    }\n}\n\nimpl SubAssign<Duration> for Instant {\n    /// Computes `Instant -= Duration`. [Read more](SubAssign)\n    ///\n    /// ## Panics\n    ///\n    /// Panics if the computed instant overflows.\n    fn sub_assign(&mut self, other: Duration) {\n        *self = *self - other;\n    }\n}\n\nimpl Sub<Instant> for Instant {\n    type Output = Duration;\n\n    /// Computes `Instant - Instant`. [Read more](Sub)","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-time/src/instant.rs#L219-L255","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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(...)`"],"exampleFix":"// before\nlet start = deadline - lead_time; // panics on underflow\n// after\nlet start = deadline.checked_sub(lead_time).unwrap_or(Instant::MIN);","handlingStrategy":"validation","validationCode":"fn safe_sub(instant: Instant, d: Duration) -> Instant {\n    instant.checked_sub(d).unwrap_or(Instant::MIN)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","embedded","overflow","time"],"backgroundTag":"value-out-of-range","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"}