pola-rs/polars · error

addition overflow: +

Error message

addition overflow: {self:?} + {other:?}

What it means

RowCounter::add panics with 'addition overflow: {self:?} + {other:?}' when combining two counters overflows (checked_add returns None). RowCounter tracks physical_rows and deleted_rows as usize, so very large counts or pathological subtraction-produced values can overflow usize.

Solutions

  1. Trace which code path produced the overflowing counter (the Debug output in the message shows both operands) and fix the upstream count
  2. Avoid resolving slices/counters near usize::MAX; check intermediate values
  3. Ensure subtraction (sub) results stay non-negative and sane before adding
  4. On 32-bit platforms, reduce dataset chunking so row counts stay in range
Defensive patterns

Strategy: try-catch

Validate before calling

def safe_add(a, b, limit):
    if a + b > limit:
        raise OverflowError(f"addition overflow: {a} + {b}")
    return a + b

Try / catch

import polars as pl
try:
    out = df.slice(offset, length)  # path that resolves negative slices
except pl.exceptions.PolarsPanicError as e:
    if "addition overflow" in str(e):
        out = handle_overflow(df)
    else:
        raise

Prevention

When it happens

Trigger: Calling add() (directly or via apply_to_df, resolve_negative_slice, or run) with counters whose row counts sum beyond usize::MAX, or adding to a counter previously built from negative-slice resolution edge cases.

Common situations: Resolution of negative slices in extreme sparse data; a usize::MAX-sized count produced by an earlier bug; 32-bit targets overflowing far sooner than 64-bit ones.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/d3cb57767c421f43. Report an issue: GitHub.

Appendix: source

Thrown at crates/polars-utils/src/row_counter.rs:97

    pub fn add(self, other: Self) -> Self {
        (|| {
            let physical_rows = self.physical_rows.checked_add(other.physical_rows);
            let deleted_rows = self.deleted_rows.checked_add(other.deleted_rows)?;

            let physical_rows = if deleted_rows == 0 {
                physical_rows.unwrap_or(usize::MAX)
            } else {
                // If there are row deletions we cannot saturate the position properly (the
                // `num_rows()` will start to decrease).
                physical_rows?
            };

            Some(Self {
                physical_rows,
                deleted_rows,
            })
        })()
        .unwrap_or_else(|| panic!("addition overflow: {self:?} + {other:?}"))
    }

    /// # Panics
    /// Panics if subtraction overflows.
    #[allow(clippy::should_implement_trait)]
    pub fn sub(self, other: Self) -> Self {
        let func = |a: usize, b: usize| {
            a.checked_sub(b)
                .unwrap_or_else(|| panic!("subtraction overflow: {self:?} - {other:?}"))
        };

        Self {
            physical_rows: func(self.physical_rows, other.physical_rows),
            deleted_rows: func(self.deleted_rows, other.deleted_rows),
        }
    }

    /// Returns the number of rows after applying deletions. This returns an

View on GitHub (pinned to fe841f959e)