pola-rs/polars · error · CopyNotAllowedError
non-contiguous buffer must be made contiguous
Error message
non-contiguous buffer must be made contiguous
What it means
Raised by the dataframe interchange protocol (PolarsBuffer.__init__) when the backing Series has more than one chunk and allow_copy=False. Serving a contiguous buffer view requires rechunking, which copies memory, so zero-copy consumers get a CopyNotAllowedError (a RuntimeError subclass).
Source
Thrown at py-polars/src/polars/interchange/buffer.py:36
class PolarsBuffer(Buffer):
"""
A buffer object backed by a Polars Series consisting of a single chunk.
Parameters
----------
data
The Polars Series backing the buffer object.
allow_copy
Allow data to be copied during operations on this column. If set to `False`,
a RuntimeError will be raised if data would be copied.
"""
def __init__(self, data: Series, *, allow_copy: bool = True) -> None:
if data.n_chunks() > 1:
if not allow_copy:
msg = "non-contiguous buffer must be made contiguous"
raise CopyNotAllowedError(msg)
data = data.rechunk()
self._data = data
@property
def bufsize(self) -> int:
"""Buffer size in bytes."""
dtype = polars_dtype_to_dtype(self._data.dtype)
if dtype[0] == DtypeKind.BOOL:
_, offset, length = self._data._get_buffer_info()
n_bits = offset + length
n_bytes, rest = divmod(n_bits, 8)
# Round up to the nearest byte
if rest == 0:
return n_bytes
else:
return n_bytes + 1View on GitHub (pinned to df599052da)
Solutions
- Call df.rechunk() (or series.rechunk()) before handing data to the interchange consumer
- Pass allow_copy=True if a copy is acceptable
- Reduce chunk fragmentation at the source (e.g. avoid repeated concat/vstack of small frames)
Example fix
// before exchange_df = df.__dataframe__(allow_copy=False) // after df = df.rechunk() exchange_df = df.__dataframe__(allow_copy=False)
Defensive patterns
Strategy: validation
Validate before calling
if df.get_column(df.columns[0]).n_chunks() > 1:
df = df.rechunk() # before requesting allow_copy=False interchange Type guard
def is_chunk_contiguous(df) -> bool:
return all(n == 1 for n in df.n_chunks('all')) Try / catch
from polars.interchange.protocol import CopyNotAllowedError
try:
dfi = df.__dataframe__(allow_copy=False)
except CopyNotAllowedError:
dfi = df.rechunk().__dataframe__(allow_copy=False) Prevention
- Rechunk after concat-heavy construction
- Test zero-copy paths with multi-chunk fixtures
- Treat CopyNotAllowedError as a signal of chunk fragmentation, not a polars bug
When it happens
Trigger: Calling __dataframe__(allow_copy=False) on a DataFrame/Series whose columns have n_chunks() > 1; interchange consumers like query compilers (pandas via protocol, ibis) that request zero copy; building a DataFrame from concatenated parts and handing it to the interchange API.
Common situations: Data assembled from scans/concat retains chunking; libraries that strictly pass allow_copy=False per the interchange spec; performance-sensitive pipelines that forbid hidden copies.
Related errors
- unevenly chunked columns must be rechunked
- string buffers must be converted
- data buffer must be cast from {data_dtype} to UInt32
- byte-packed boolean buffer must be converted to bit-packed b
- offsets buffer must be cast from {polars_dtype} to Int64
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/6d8c9b9388468f6a.
Report an issue: GitHub.