pola-rs/polars · error · CopyNotAllowedError
byte-packed boolean buffer must be converted to bit-packed…
Error message
byte-packed boolean buffer must be converted to bit-packed boolean
What it means
The interchange protocol allows boolean buffers to be bit-packed (1 bit per value) or byte-packed (8 bits per value, dtype[1] == 8). Polars represents booleans bit-packed, so a byte-packed buffer must be wrapped as UInt8 and cast to Boolean — a copy. With allow_copy=False and a non-empty buffer this raises CopyNotAllowedError; length-0 buffers return an empty Boolean Series.
Solutions
- Call pl.from_dataframe(obj, allow_copy=True) to permit the UInt8->Boolean cast.
- Have the producer bit-pack boolean columns before export.
- Catch CopyNotAllowedError and retry with allow_copy=True.
Example fix
# before df = pl.from_dataframe(obj, allow_copy=False) # byte-packed bool -> CopyNotAllowedError # after df = pl.from_dataframe(obj, allow_copy=True)
Defensive patterns
Strategy: fallback
Validate before calling
def has_byte_packed_bools(icdf) -> bool:
return any(
(c := icdf.get_column(i)).dtype[:2] == (DtypeKind.BOOL, 8) and c.size() > 0
for i in range(icdf.num_columns())
)
allow_copy = not has_byte_packed_bools(obj.__dataframe__()) Try / catch
from polars.interchange.protocol import CopyNotAllowedError
try:
df = pl.from_dataframe(obj, allow_copy=False)
except CopyNotAllowedError:
df = pl.from_dataframe(obj, allow_copy=True) # allows UInt8 -> Boolean cast Prevention
- Assume numpy-backed producers emit byte-packed booleans.
- Bit-pack boolean buffers on the producer if zero-copy transfer is mandatory.
When it happens
Trigger: pl.from_dataframe(obj, allow_copy=False) where a boolean column's dtype tuple has bit width 8 — the natural layout for numpy bool masks and several interchange producers.
Common situations: Importing from producers backed by numpy bool arrays; zero-copy pipelines that also carry flag/mask columns; mixed-width boolean handling in custom interop code.
Related errors
- bitmask must be constructed
- bitmask must be inverted
- bytemask must be converted into a bitmask
- data buffer must be cast from
- offsets buffer must be cast from
AI-assisted analysis of pola-rs/polars@9b5d73fd00 (2026-08-19).
Data as JSON: /api/errors/1ae18d18fa74ab44.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/interchange/from_dataframe.py:215
*,
allow_copy: bool,
) -> Series:
polars_dtype = dtype_to_polars_dtype(dtype)
# Handle implementations that incorrectly set the data buffer dtype
# to the column dtype
# https://github.com/pola-rs/polars/pull/10787
polars_dtype = polars_dtype_to_data_buffer_dtype(polars_dtype)
buffer_info = (buffer.ptr, offset, length)
# Handle byte-packed boolean buffer
if polars_dtype == Boolean and dtype[1] == 8:
if length == 0:
return pl.Series(dtype=Boolean)
elif not allow_copy:
msg = "byte-packed boolean buffer must be converted to bit-packed boolean"
raise CopyNotAllowedError(msg)
return pl.Series._from_buffer(UInt8, buffer_info, owner=buffer).cast(Boolean)
return pl.Series._from_buffer(polars_dtype, buffer_info, owner=buffer)
def _construct_offsets_buffer(
buffer: Buffer,
dtype: Dtype,
offset: int,
*,
allow_copy: bool,
) -> Series:
polars_dtype = dtype_to_polars_dtype(dtype)
length = get_buffer_length_in_elements(buffer.bufsize, dtype) - offset
buffer_info = (buffer.ptr, offset, length)
s = pl.Series._from_buffer(polars_dtype, buffer_info, owner=buffer)
View on GitHub (pinned to 9b5d73fd00)