pandas-dev/pandas · error · ValueError

Cannot modify read-only array

Error message

Cannot modify read-only array

What it means

Raised (ValueError) from ExtensionArray.__setitem__ when `self._readonly` is True. pandas marks arrays as read-only (sets the numpy WRITEABLE flag off and `_readonly=True`) when they are backed by memory that must not be mutated — typically zero-copy views into another array's buffer. Any in-place assignment is rejected to prevent corrupting the source buffer.

Solutions

  1. Take a writable copy before mutating: `arr = arr.copy()`, then assign.
  2. Operate on a fresh Series/DataFrame via normal pandas assignment rather than mutating a view extracted with `.values`.
  3. If you must edit in place, ensure you own the buffer (construct from a copy, not a view).

Example fix

# before
view = ser.values      # may be read-only
view[0] = 99
# after
arr = ser.values.copy()
arr[0] = 99
Defensive patterns

Strategy: type-guard

Validate before calling

if getattr(arr, '_readonly', False):
    raise ValueError("array is read-only; copy before mutating")
arr[0] = value

Type guard

def is_writable(arr) -> bool:
    return not getattr(arr, '_readonly', False)

Try / catch

try:
    arr[0] = value
except ValueError as e:
    if "read-only" in str(e):
        arr = arr.copy(); arr[0] = value
    else:
        raise

Prevention

When it happens

Trigger: Calling `arr[i] = value`, `arr[mask] = value`, or `Series.iloc[...] = ...` where the underlying ExtensionArray was obtained via a zero-copy operation (e.g. `.values`, `.to_numpy()` views, or array slices that share memory) that left `_readonly=True`.

Common situations: Mutating an array returned by `.values`/`.to_numpy()` which pandas may mark read-only to protect shared buffers; in-place edits on views produced by zero-copy constructors.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/82ff92e4acd21bb8. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/arrays/base.py:569

        # *do* choose to implement __setitem__, then some semantics should be
        # observed:
        #
        # * Setting multiple values : ExtensionArrays should support setting
        #   multiple values at once, 'key' will be a sequence of integers and
        #  'value' will be a same-length sequence.
        #
        # * Broadcasting : For a sequence 'key' and a scalar 'value',
        #   each position in 'key' should be set to 'value'.
        #
        # * Coercion : Most users will expect basic coercion to work. For
        #   example, a string like '2018-01-01' is coerced to a datetime
        #   when setting on a datetime64ns array. In general, if the
        #   __init__ method coerces that value, then so should __setitem__
        # Note, also, that Series/DataFrame.where internally use __setitem__
        # on a copy of the data.
        # Check if the array is readonly
        if self._readonly:
            raise ValueError("Cannot modify read-only array")

        raise NotImplementedError(f"{type(self)} does not implement __setitem__.")

    def __len__(self) -> int:
        """
        Length of this array

        Returns
        -------
        length : int
        """
        raise AbstractMethodError(self)

    def __iter__(self) -> Iterator[Any]:
        """
        Iterate over elements of the array.
        """
        # This needs to be implemented so that pandas recognizes extension

View on GitHub (pinned to 3b7651241d)