pola-rs/polars · error
copy not allowed: cast from {arr.dtype} to {dtype} prohibite
Error message
copy not allowed: cast from {arr.dtype} to {dtype} prohibited What it means
Raised (as RuntimeError, not TypeError) inside Series.__array__ when copy=False was requested but the produced array's dtype differs from the requested dtype, so honoring the request would require a copy. Zero-copy handoff only works when the numpy dtype matches the Series' native representation (e.g. Int64 -> int64, Float64 -> float64, Utf8View -> no match); any cast triggers this.
Source
Thrown at py-polars/src/polars/series/series.py:1614
dtype = np.dtype("U")
if copy is None:
writable, allow_copy = False, True
elif copy is True:
writable, allow_copy = True, True
elif copy is False:
writable, allow_copy = False, False
else:
msg = f"invalid input for `copy`: {copy!r}"
raise TypeError(msg)
arr = self.to_numpy(writable=writable, allow_copy=allow_copy)
if dtype is not None and dtype != arr.dtype:
if copy is False:
# TODO: Only raise when data must be copied
msg = f"copy not allowed: cast from {arr.dtype} to {dtype} prohibited"
raise RuntimeError(msg)
arr = arr.__array__(dtype)
return arr
def __array_ufunc__(
self, ufunc: np.ufunc, method: str_, *inputs: Any, **kwargs: Any
) -> Series:
"""Numpy universal functions."""
if self._s.n_chunks() > 1:
self._s.rechunk(in_place=True)
s = self._s
if method == "__call__":
if ufunc.nout != 1:
msg = "only ufuncs that return one 1D array are supported"
raise NotImplementedError(msg)View on GitHub (pinned to df599052da)
Solutions
- Drop copy=False (default allows the copy), or align the requested dtype with the native one: `np.asarray(s, dtype=np.int64, copy=False)` for an Int64 Series.
- Make the copy explicit and controlled: `arr = s.to_numpy(); arr32 = arr.astype(np.float32)`.
- Cast the Series first so the numpy conversion is already in the target dtype: `s.cast(pl.Float32).to_numpy()`.
- Note the TODO in source: the check is coarse - it raises even when a copy might not strictly be needed - so do not rely on copy=False across dtype boundaries.
Example fix
// before s = pl.Series([1, 2, 3], dtype=pl.Int64) np.asarray(s, dtype=np.float32, copy=False) # RuntimeError // after s.cast(pl.Float32).to_numpy() # or accept the copy: np.asarray(s, dtype=np.float32)
Defensive patterns
Strategy: validation
Validate before calling
NATIVE = {pl.Int64: np.int64, pl.Float64: np.float64, pl.Int32: np.int32, pl.Float32: np.float32}
if np.asarray(s).dtype != target and copy is False:
s = s.cast(next(k for k, v in NATIVE.items() if v == target))
arr = np.asarray(s, dtype=target, copy=False) Type guard
def zero_copy_compatible(s: pl.Series, dtype: np.dtype) -> bool:
return np.asarray(s).dtype == dtype Try / catch
try:
arr = np.asarray(s, dtype=target, copy=False)
except RuntimeError as e:
if 'copy not allowed' not in str(e):
raise
arr = np.asarray(s, dtype=target) # allow the copy Prevention
- copy=False is a hard 'never copy' guarantee in NumPy 2 - only pair it with the native dtype.
- Cast the Series first (s.cast(pl.Float32).to_numpy()) to control where the copy happens.
- Note this raises even for cases where a copy might be avoidable (source TODO).
When it happens
Trigger: `np.asarray(s, dtype=np.float32, copy=False)` on an Int64 or Float64 Series; `np.asarray(s, dtype=np.int32, copy=False)` on Int64; requesting U/str dtypes on a String Series together with copy=False; the String->'U' auto-dtype branch only applies when dtype is None.
Common situations: NumPy 2 'copy=False means never copy' migrations - old code where copy=False meant 'avoid if possible' now must guarantee exact dtype; performance-tuned pipelines passing copy=False to avoid allocation while still asking for a different precision.
Related errors
- invalid input for `copy`: {copy!r}
- only ufuncs that return one 1D array are supported
- unsupported type {qualified_type_name(arg)!r} for {arg!r}
- can't pass a Series with missing data to a generalized ufunc
- could not find `apply_ufunc_{numpy_char_code_to_dtype(dtype_
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/b1202cf32b5e6716.
Report an issue: GitHub.