{"record":{"id":"c822c28d84664306","repo":"embassy-rs/embassy","slug":"overflow-when-adding-duration-to-instant","errorCode":null,"errorMessage":"overflow when adding duration to instant","messagePattern":"overflow when adding duration to instant","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-time/src/instant.rs","lineNumber":212,"sourceCode":"    /// Subtracts a Duration from self. In case of overflow, the minimum value is returned.\n    #[inline]\n    pub const fn saturating_sub(mut self, duration: Duration) -> Self {\n        self.ticks = self.ticks.saturating_sub(duration.ticks);\n        self\n    }\n}\n\nimpl Add<Duration> for Instant {\n    type Output = Instant;\n\n    /// Computes `Instant + Duration`. [Read more](Add)\n    ///\n    /// ## Panics\n    ///\n    /// Panics if the computed instant overflows.\n    fn add(self, other: Duration) -> Instant {\n        self.checked_add(other)\n            .expect(\"overflow when adding duration to instant\")\n    }\n}\n\nimpl AddAssign<Duration> for Instant {\n    /// Computes `Instant += Duration`. [Read more](AddAssign)\n    ///\n    /// ## 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)","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-time/src/instant.rs#L194-L230","documentation":"Instant + Duration arithmetic in embassy-time panics when the resulting Instant tick value overflows the underlying 64-bit tick representation. The Add impl delegates to checked_add and expects success, so any overflowing addition aborts the task. This guards against silently wrapping instants, which would corrupt all timeout/scheduling math.","triggerScenarios":"Calling `instant + duration` (or `+=`, which routes through add) where `instant.ticks + duration.ticks` exceeds i64::MAX ticks — e.g. adding huge Durations like `Duration::from_secs(u64::MAX)` or repeated additions from a large base instant.","commonSituations":"Computing deadlines with unvalidated user-supplied durations, accumulating timeouts in a loop without saturation, or migrating from libraries where Duration was larger/smaller scale so old constants now overflow.","solutions":["Use `Instant::checked_add(duration)` and handle the None case instead of `+`","Use `Instant::now() + duration` with a bounded/saturated duration (cap via `duration.min(Duration::from_secs(...))`)","Verify the Duration constant is expressed in the intended unit (ticks vs micros) before adding"],"exampleFix":"// before\nlet deadline = start + user_duration; // panics on overflow\n// after\nlet deadline = start.checked_add(user_duration).unwrap_or(Instant::MAX);","handlingStrategy":"validation","validationCode":"fn safe_add(instant: Instant, d: Duration) -> Instant {\n    instant.checked_add(d).unwrap_or(Instant::MAX)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always prefer checked_add/checked_sub for Instant arithmetic with dynamic durations","Clamp externally sourced Durations to a sane maximum before use","Add unit tests with Duration::MAX to catch overflow paths"],"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"}