{"record":{"id":"102b128912dd249b","repo":"databendlabs/databend","slug":"product-resulted-in-nan","errorCode":null,"errorMessage":"Product resulted in NaN","messagePattern":"Product resulted in NaN","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/common/base/src/base/ordered_float.rs","lineNumber":1366,"sourceCode":"        NotNan::new(self.0 - other).expect(\"Subtraction resulted in NaN\")\n    }\n}\n\n/// Multiplies a float directly.\n///\n/// Panics if the provided value is NaN or the computation results in NaN\nimpl<T: FloatCore> Mul<T> for NotNan<T> {\n    type Output = Self;\n\n    #[inline]\n    fn mul(self, other: T) -> Self {\n        NotNan::new(self.0 * other).expect(\"Multiplication resulted in NaN\")\n    }\n}\n\nimpl<T: FloatCore + Product> Product for NotNan<T> {\n    fn product<I: Iterator<Item = NotNan<T>>>(iter: I) -> Self {\n        NotNan::new(iter.map(|v| v.0).product()).expect(\"Product resulted in NaN\")\n    }\n}\n\nimpl<'a, T: FloatCore + Product + 'a> Product<&'a NotNan<T>> for NotNan<T> {\n    #[inline]\n    fn product<I: Iterator<Item = &'a NotNan<T>>>(iter: I) -> Self {\n        iter.cloned().product()\n    }\n}\n\n/// Divides a float directly.\n///\n/// Panics if the provided value is NaN or the computation results in NaN\nimpl<T: FloatCore> Div<T> for NotNan<T> {\n    type Output = Self;\n\n    #[inline]\n    fn div(self, other: T) -> Self {","sourceCodeStart":1348,"sourceCodeEnd":1384,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/common/base/src/base/ordered_float.rs#L1348-L1384","documentation":"The Product impl for NotNan<T> folds the iterator's floats with std's Product and rewraps with NotNan::new, panicking with this message if the product is NaN. A NaN product occurs when any factor is NaN or when a zero factor meets an infinite intermediate product (0 * inf).","triggerScenarios":"`iter.product::<NotNan<f64>>()` where the running product overflows to inf and a later factor is 0.0, or where any factor is NaN (only reachable through unsafe NotNan construction or raw-value paths).","commonSituations":"Computing joint probabilities or compounded rates where underflow/overflow to 0/inf mixes with exact zeros; also product-reductions over sensor readings containing NaN sourced from upstream division by zero.","solutions":["Validate all factors with `is_finite()` before folding; filter or short-circuit degenerate products.","Compute in f64 and wrap fallibly: `NotNan::new(vals.iter().product::<f64>()).ok()` with explicit NaN handling.","Use logs/stable transforms for large products to avoid inf intermediates that later cancel against zeros."],"exampleFix":"// before\nlet p: NotNan<f64> = factors.iter().copied().product(); // 0 * inf panics\n// after\nlet p = if factors.iter().any(|v| !v.is_finite() || **v == 0.0) { None } else { Some(factors.iter().copied().product::<NotNan<f64>>()) };","handlingStrategy":"validation","validationCode":"fn safe_product(vals: &[NotNan<f64>]) -> Option<NotNan<f64>> {\n    let mut acc = 1.0f64;\n    for v in vals {\n        acc *= v.0;\n        if acc.is_nan() { return None; }\n    }\n    NotNan::new(acc).ok()\n}","typeGuard":"fn all_finite_nonzero_ok(vals: &[NotNan<f64>]) -> bool { vals.iter().all(|v| v.is_finite()) }","tryCatchPattern":"let p = std::panic::catch_unwind(|| vals.iter().copied().product::<NotNan<f64>>()).ok();","preventionTips":["Track the running product and bail out early if it becomes inf or NaN.","Filter NaN/zeros when infinite factors are possible.","Use log-space accumulation for large products to avoid inf intermediates."],"tags":["rust","float","nan","product","aggregation","panic"],"backgroundTag":"nan-arithmetic-panic","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}