{"record":{"id":"efe317766bd1f3de","repo":"embassy-rs/embassy","slug":"overflow-when-multiplying-duration-by-scalar","errorCode":null,"errorMessage":"overflow when multiplying duration by scalar","messagePattern":"overflow when multiplying duration by scalar","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-time/src/duration.rs","lineNumber":265,"sourceCode":"    /// ## 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)\n    ///\n    /// ## Panics\n    ///\n    /// Panics if the computed duration overflows.\n    fn mul(self, rhs: u32) -> Duration {\n        self.checked_mul(rhs)\n            .expect(\"overflow when multiplying duration by scalar\")\n    }\n}\n\nimpl Mul<Duration> for u32 {\n    type Output = Duration;\n\n    /// Computes `u32 * Duration`. [Read more](Mul)\n    ///\n    /// ## Panics\n    ///\n    /// Panics if the computed duration overflows.\n    fn mul(self, rhs: Duration) -> Duration {\n        rhs * self\n    }\n}\n\nimpl MulAssign<u32> for Duration {\n    /// Computes `Duration *= u32`. [Read more](MulAssign)","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-time/src/duration.rs#L247-L283","documentation":"`Duration * u32` in embassy-time is implemented via `checked_mul`; if the scaled tick count overflows the duration representation, `.expect(\"overflow when multiplying duration by scalar\")` panics. Std's `Duration` behaves the same way (documented panic on overflow).","triggerScenarios":"`duration * factor` where `duration` is large and `factor` pushes the product past `Duration::MAX` (e.g. `Duration::from_secs(u32::MAX) * u32::MAX` style scaling, or multiplying microsecond-precision values by big multipliers).","commonSituations":"Exponential backoff multipliers applied to already-large timeouts; converting units (multiplying by 1_000_000) on large second values; retry loops where the delay keeps multiplying.","solutions":["Use checked arithmetic: `d.checked_mul(n).unwrap_or(Duration::MAX)`","Cap the base duration before scaling (start backoff from a small value and cap the max delay)","Reduce precision first (convert to seconds before multiplying) when sub-microsecond precision isn't needed"],"exampleFix":"// before\nlet delay = base * backoff_factor; // panics when large\n// after\nlet delay = base.checked_mul(backoff_factor).unwrap_or(Duration::from_secs(3600));","handlingStrategy":"validation","validationCode":"fn safe_mul(d: embassy_time::Duration, n: u32) -> embassy_time::Duration {\n    d.checked_mul(n).unwrap_or(embassy_time::Duration::MAX)\n}","typeGuard":null,"tryCatchPattern":"// Panic is not catchable in embedded; use checked mul:\nlet scaled = d.checked_mul(n).ok_or(CalcError::Overflow)?;","preventionTips":["Cap backoff/timeout base values before scaling","Prefer checked_mul whenever the multiplier is runtime data","Reduce precision (use seconds not micros) for large products"],"tags":["arithmetic","duration","overflow","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"}