pola-rs/polars · error · RuntimeError

copy not allowed: cast from

Error message

copy not allowed: cast from {arr.dtype} to {dtype} prohibited

What it means

When `copy=False` is requested in Series.__array__, polars promises a zero-copy numpy view. If the requested dtype differs from the produced array's dtype, the cast would require copying data, so a RuntimeError is raised instead of silently violating the no-copy contract.

Solutions

  1. Allow copying: call with `copy=True` (or omit copy)
  2. Request the dtype the Series naturally produces (match `arr.dtype`, e.g. cast the Series in polars first: `series.cast(pl.Int32)` then convert)
  3. Only pass a dtype when it equals the Series' numpy dtype; check `series.to_numpy().dtype` beforehand

Example fix

// before
arr = s.__array__(dtype=np.int32, copy=False)  # RuntimeError
// after
arr = s.cast(pl.Int32).to_numpy()  # or allow copy=True
Defensive patterns

Strategy: validation

Validate before calling

target = np.dtype(dtype)
arr0 = series.to_numpy()
if target != arr0.dtype and copy is False:
    raise ValueError("requested dtype differs; copy=False would need a cast")

Type guard

def is_zero_copy_cast(series: pl.Series, dtype: np.dtype) -> bool:
    return dtype is None or np.dtype(dtype) == series.to_numpy().dtype

Try / catch

try:
    arr = series.__array__(dtype=dtype, copy=False)
except RuntimeError as e:
    if "copy not allowed" in str(e):
        arr = series.__array__(dtype=dtype, copy=True)
    else:
        raise

Prevention

When it happens

Trigger: `series.__array__(dtype=np.int32, copy=False)` or `np.asarray(series, dtype=..., copy=False)` where `dtype != arr.dtype` (e.g. requesting a cast from Int64 to Float64 or to a different width) at py-polars/src/polars/series/series.py:1500.

Common situations: Interop code forcing a dtype while also forbidding copies; date/datetime series converted to numpy with a different dtype requested; strict zero-copy pipelines that changed the target dtype.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/b1202cf32b5e6716. Report an issue: GitHub.

Appendix: source

Thrown at py-polars/src/polars/series/series.py:1500

            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 fe841f959e)