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
- Take a writable copy before mutating: `arr = arr.copy()`, then assign.
- Operate on a fresh Series/DataFrame via normal pandas assignment rather than mutating a view extracted with `.values`.
- 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
- Copy arrays returned by .values/.to_numpy() before mutating
- Prefer pandas-level assignment over mutating extracted buffers
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
- Cannot modify read-only array
- SparseArray does not support item assignment via setitem
- does not implement __setitem__.
- can only convert an array of size 1 to a Python scalar
- cannot diff on axis=
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 extensionView on GitHub (pinned to 3b7651241d)