{"record":{"id":"06c2e8a80c19c421","repo":"embassy-rs/embassy","slug":"divide-by-zero-error-when-dividing-duration-by-sca","errorCode":null,"errorMessage":"divide by zero error when dividing duration by scalar","messagePattern":"divide by zero error when dividing duration by scalar","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-time/src/duration.rs","lineNumber":303,"sourceCode":"    /// ## Panics\n    ///\n    /// Panics if the computed duration overflows.\n    fn mul_assign(&mut self, rhs: u32) {\n        *self = *self * rhs;\n    }\n}\n\nimpl Div<u32> for Duration {\n    type Output = Duration;\n\n    /// Computes `Duration / u32`. [Read more](Div)\n    ///\n    /// ## Panics\n    ///\n    /// Panics if dividing by zero.\n    fn div(self, rhs: u32) -> Duration {\n        self.checked_div(rhs)\n            .expect(\"divide by zero error when dividing duration by scalar\")\n    }\n}\n\nimpl DivAssign<u32> for Duration {\n    /// Computes `Duration /= u32`. [Read more](DivAssign)\n    ///\n    /// ## Panics\n    ///\n    /// Panics if dividing by zero.\n    fn div_assign(&mut self, rhs: u32) {\n        *self = *self / rhs;\n    }\n}\n\nimpl<'a> fmt::Display for Duration {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"{} ticks\", self.ticks)\n    }","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-time/src/duration.rs#L285-L321","documentation":"`Duration / u32` in embassy-time is implemented via `checked_div`, which returns `None` only when the divisor is zero; `.expect(\"divide by zero error when dividing duration by scalar\")` then panics. The message is misleading if you suspect overflow — division overflow is not the trigger, only `rhs == 0` (mirroring std's documented panic-on-divide-by-zero).","triggerScenarios":"`duration / n` where `n` is a `u32` that is 0 — e.g. a computed divisor from an empty collection's `len()`, or an uninitialized/config-missing variable used as the divisor.","commonSituations":"Splitting a timeout across N items where N comes from an empty list; averaging over a count that can be zero; unit conversion where the divisor is read from config that defaulted to 0.","solutions":["Check the divisor before dividing: `if n == 0 { ... } else { duration / n }`","Clamp to at least 1: `duration / n.max(1)`","Return a sensible default when the divisor is zero: `duration.checked_div(n).unwrap_or(Duration::ZERO)`"],"exampleFix":"// before\nlet per_item = total_timeout / item_count; // panics if item_count == 0\n// after\nlet per_item = total_timeout / item_count.max(1);","handlingStrategy":"validation","validationCode":"fn safe_div(d: embassy_time::Duration, n: u32) -> embassy_time::Duration {\n    d.checked_div(n).unwrap_or(embassy_time::Duration::ZERO)\n}","typeGuard":null,"tryCatchPattern":"// Panic is not catchable in embedded; guard the divisor:\nif n == 0 { return Duration::ZERO; }\nlet per = d / n;","preventionTips":["Never divide a duration by a value derived from .len() of a possibly-empty collection","Clamp divisors with .max(1)","Treat zero divisors from config as a validation error at startup"],"tags":["arithmetic","duration","divide-by-zero","panic"],"backgroundTag":"division-by-zero","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"}