pola-rs/polars · error · ValueError

`n_chunks` must be a multiple of the number of chunks of thi

Error message

`n_chunks` must be a multiple of the number of chunks of this column ({total_n_chunks})

What it means

Raised by PolarsColumn.get_chunks when the requested n_chunks is <= 0 or is not an integer multiple of the column's actual chunk count. The interchange chunking logic can only evenly subdivide existing chunks, so arbitrary counts are rejected.

Source

Thrown at py-polars/src/polars/interchange/column.py:137

        -----
        When `n_chunks` is higher than the number of chunks in the column, a slice
        must be performed that is not on the chunk boundary. This will trigger some
        compute if the column contains null values or if the column is of data type
        boolean.
        """
        total_n_chunks = self.num_chunks()
        chunks = self._col.get_chunks()

        if (n_chunks is None) or (n_chunks == total_n_chunks):
            for chunk in chunks:
                yield PolarsColumn(chunk, allow_copy=self._allow_copy)

        elif (n_chunks <= 0) or (n_chunks % total_n_chunks != 0):
            msg = (
                "`n_chunks` must be a multiple of the number of chunks of this column"
                f" ({total_n_chunks})"
            )
            raise ValueError(msg)

        else:
            subchunks_per_chunk = n_chunks // total_n_chunks
            for chunk in chunks:
                size = len(chunk)
                step = size // subchunks_per_chunk
                if size % subchunks_per_chunk != 0:
                    step += 1
                for start in range(0, step * subchunks_per_chunk, step):
                    yield PolarsColumn(
                        chunk[start : start + step], allow_copy=self._allow_copy
                    )

    def get_buffers(self) -> ColumnBuffers:
        """Return a dictionary containing the underlying buffers."""
        dtype = self._col.dtype

        if dtype == String and not self._allow_copy:

View on GitHub (pinned to df599052da)

Solutions

  1. Pass n_chunks=None to iterate the natural chunks, or n_chunks equal to a multiple of column.num_chunks()
  2. Compute the request dynamically: n_chunks = column.num_chunks() * k for the subdivision factor k you need
  3. Validate n_chunks > 0 before calling

Example fix

// before
chunks = list(col.get_chunks(3))  # col has 2 chunks
// after
k = math.ceil(3 / col.num_chunks())
chunks = list(col.get_chunks(col.num_chunks() * k))
# or simply: chunks = list(col.get_chunks())
Defensive patterns

Strategy: validation

Validate before calling

total = column.num_chunks()
ok = n_chunks is None or (n_chunks > 0 and n_chunks % total == 0)

Type guard

def is_valid_chunk_request(n_chunks: int, total: int) -> bool:
    return n_chunks > 0 and n_chunks % total == 0

Try / catch

try:
    chunks = list(column.get_chunks(n))
except ValueError:
    chunks = list(column.get_chunks())  # fall back to natural chunking

Prevention

When it happens

Trigger: column.get_chunks(3) on a column with 2 chunks (3 % 2 != 0); get_chunks(0) or a negative value; consumers computing n_chunks from a target batch size without aligning to the source chunk count.

Common situations: Streaming/batching code that asks for a fixed number of chunks (e.g. batch_size-driven); interleaving chunk requests across columns assuming all columns share one chunk count; calling num_chunks() once and then reusing a stale value after the frame changed.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/66c5f85b234a8f3f. Report an issue: GitHub.