pola-rs/polars · error · CopyNotAllowedError
bytemask must be converted into a bitmask
Error message
bytemask must be converted into a bitmask
What it means
USE_BYTEMASK validity (one byte per row) must always be converted into Polars' bit-packed boolean validity — there is no zero-copy path. _construct_validity_buffer_from_bytemask checks allow_copy before even reading the buffer and raises CopyNotAllowedError('bytemask must be converted into a bitmask') when copying is disallowed; an additional inversion applies when null_value != 0.
Solutions
- Call pl.from_dataframe(obj, allow_copy=True) to permit the bytemask-to-bitmask conversion.
- Have the producer bit-pack validity into a USE_BITMAP buffer instead.
- Catch CopyNotAllowedError and retry with allow_copy=True.
Example fix
# before df = pl.from_dataframe(obj, allow_copy=False) # bytemask column -> CopyNotAllowedError # after df = pl.from_dataframe(obj, allow_copy=True) # bytemask converted to bitmask
Defensive patterns
Strategy: fallback
Validate before calling
def uses_bytemask(icdf) -> bool:
return any(
icdf.get_column(i).describe_null()[0] == ColumnNullType.USE_BYTEMASK
for i in range(icdf.num_columns())
)
allow_copy = not uses_bytemask(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 bytemask -> bitmask conversion Prevention
- Bytemask validity can never be zero-copy with Polars — bit-pack it on the producer.
- Introspect describe_null() before promising zero-copy conversion to callers.
When it happens
Trigger: pl.from_dataframe(obj, allow_copy=False) where describe_null()[0] == ColumnNullType.USE_BYTEMASK — the natural encoding when a producer's validity mask is a numpy uint8/bool array.
Common situations: Custom or numpy-backed interchange producers exporting per-byte masks; zero-copy pipelines that hit any bytemask column and fail immediately.
Related errors
- bitmask must be constructed
- bitmask must be inverted
- byte-packed boolean buffer must be converted to bit-packed…
- 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/c8e5618bc04c04cc.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/interchange/from_dataframe.py:326
if null_value != 0:
if not allow_copy:
msg = "bitmask must be inverted"
raise CopyNotAllowedError(msg)
s = ~s
return s
def _construct_validity_buffer_from_bytemask(
buffer: Buffer,
null_value: int,
*,
allow_copy: bool,
) -> Series:
if not allow_copy:
msg = "bytemask must be converted into a bitmask"
raise CopyNotAllowedError(msg)
buffer_info = (buffer.ptr, 0, buffer.bufsize)
s = pl.Series._from_buffer(UInt8, buffer_info, owner=buffer)
s = s.cast(Boolean)
if null_value != 0:
s = ~s
return s
View on GitHub (pinned to 9b5d73fd00)