pandas-dev/pandas · error · ValueError

Unable to avoid copy while creating an array as requested.

Error message

Unable to avoid copy while creating an array as requested.

What it means

Raised by BaseMaskedArray.__array__ when NumPy (or user code) requests copy=False but the array has missing values. With NAs present pandas must materialize a copy to substitute the na_value into the masked positions, so it cannot honor a zero-copy request and raises rather than silently copying.

Source

Thrown at pandas/core/arrays/masked.py:831

    __array_priority__ = 1000  # higher than ndarray so ops dispatch to us

    def __array__(
        self, dtype: NpDtype | None = None, copy: bool | None = None
    ) -> np.ndarray:
        """
        the array interface, return my values
        We return an object array here to preserve our scalar values
        """
        if copy is False:
            if not self._hasna:
                # special case, here we can simply return the underlying data
                result = np.array(self._data, dtype=dtype, copy=copy)
                # If the ExtensionArray is readonly, make the numpy array readonly too
                if self._readonly:
                    result = result.view()
                    result.flags.writeable = False
                return result
            raise ValueError(
                "Unable to avoid copy while creating an array as requested."
            )

        if copy is None:
            copy = False  # The NumPy copy=False meaning is different here.
        return self.to_numpy(dtype=dtype, copy=copy)

    _HANDLED_TYPES: tuple[type, ...]

    def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs):
        # For MaskedArray inputs, we apply the ufunc to ._data
        # and mask the result.

        out = kwargs.get("out", ())

        for x in inputs + out:
            if not isinstance(x, (*self._HANDLED_TYPES, BaseMaskedArray)):
                return NotImplemented

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Allow a copy: call np.asarray(arr) without copy=False, or pass copy=True.
  2. Strip NAs before the no-copy conversion if you truly need a view: arr = arr[~arr.isna()] then arr.to_numpy(copy=False) on the underlying data.
  3. Use arr.to_numpy(dtype=..., na_value=...) explicitly which accepts the necessary copy.

Example fix

// before
np.asarray(nullable_arr, copy=False)  # raises if arr has NA

// after
np.asarray(nullable_arr)  # allow copy
Defensive patterns

Strategy: validation

Validate before calling

def no_copy_numpy(arr, dtype=None):
    if getattr(arr, "_hasna", False):
        raise ValueError("cannot avoid copy when array has NA")
    return np.asarray(arr, dtype=dtype)  # copy allowed/none

Type guard

def can_zero_copy_to_numpy(arr) -> bool:
    return not getattr(arr, "_hasna", False)

Try / catch

try:
    out = np.asarray(arr, copy=False)
except ValueError as e:
    if "Unable to avoid copy" in str(e):
        out = np.asarray(arr)
    else:
        raise

Prevention

When it happens

Trigger: Calling np.asarray(arr, dtype=...) with copy=False semantics (NumPy 2.0 copy keyword), or any code path that invokes __array__(copy=False) on a masked array that has NAs (self._hasna True). Also triggered by libraries that pass copy=False unconditionally.

Common situations: NumPy 2.0 introduced the copy keyword on np.asarray; downstream libraries passing copy=False to avoid copies; passing a nullable Series/array into a function asserting no-copy.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/fe600447218b8341. Report an issue: GitHub.