databendlabs/databend · error
Sum resulted in NaN
Error message
Sum resulted in NaN
What it means
The Sum impl for NotNan<T> folds the iterator's underlying floats with std's Sum and rewraps via NotNan::new. If the accumulated sum is NaN (any NaN element, or inf + -inf intermediate), NotNan::new panics with this message. The wrapper intentionally refuses to let NaN flow into ordered float collections.
Solutions
- Filter non-finite values before summing: `iter.filter(|v| v.is_finite()).sum()`.
- Collect into f64, sum, and check: `NotNan::new(vals.iter().sum::<f64>()).ok()` with explicit NaN handling.
- Fix upstream computations that emit inf (guard divisions, clamp overflow) before the sum.
Example fix
// before let total: NotNan<f64> = values.iter().copied().sum(); // panics on NaN result // after let total: NotNan<f64> = values.iter().copied().filter(|v| v.is_finite()).sum();
Defensive patterns
Strategy: validation
Validate before calling
fn safe_sum(vals: &[NotNan<f64>]) -> Option<NotNan<f64>> {
if vals.iter().all(|v| v.is_finite()) {
let raw: f64 = vals.iter().map(|v| v.0).sum();
NotNan::new(raw).ok()
} else { None }
} Type guard
fn all_finite(vals: &[NotNan<f64>]) -> bool { vals.iter().all(|v| v.is_finite()) } Try / catch
let total = std::panic::catch_unwind(|| vals.iter().copied().sum::<NotNan<f64>>()).ok();
Prevention
- Filter or reject non-finite elements before summing.
- Sum in plain f64 with explicit NaN checks, then wrap once via NotNan::new.
- Fix inf-producing computations (division by zero, overflow) upstream.
When it happens
Trigger: `iter.sum::<NotNan<f64>>()` where the iterator contains a NaN NotNan (constructible only via unsafe or prior bugs) or where the running sum becomes NaN through inf + -inf cancellation of infinite elements.
Common situations: Aggregating columns of computed values where some rows contain infinities from division by zero, so +inf and -inf sums cancel to NaN; also summing very large magnitudes that overflow to inf on both signs.
Related errors
- Product resulted in NaN
- partial_cmp failed for non-NaN value
- Addition resulted in NaN
- Subtraction resulted in NaN
- Multiplication resulted in NaN
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/30dfd60d203d525a.
Report an issue: GitHub.
Appendix: source
Thrown at src/common/base/src/base/ordered_float.rs:1329
/// Adds a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl<T: FloatCore> Add<T> for NotNan<T> {
type Output = Self;
#[inline]
fn add(self, other: T) -> Self {
NotNan::new(self.0 + other).expect("Addition resulted in NaN")
}
}
/// Adds a float directly.
///
/// Panics if the provided value is NaN.
impl<T: FloatCore + Sum> Sum for NotNan<T> {
fn sum<I: Iterator<Item = NotNan<T>>>(iter: I) -> Self {
NotNan::new(iter.map(|v| v.0).sum()).expect("Sum resulted in NaN")
}
}
impl<'a, T: FloatCore + Sum + 'a> Sum<&'a NotNan<T>> for NotNan<T> {
#[inline]
fn sum<I: Iterator<Item = &'a NotNan<T>>>(iter: I) -> Self {
iter.cloned().sum()
}
}
/// Subtracts a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl<T: FloatCore> Sub<T> for NotNan<T> {
type Output = Self;
#[inline]
fn sub(self, other: T) -> Self {View on GitHub (pinned to 288d84d76e)