pandas-dev/pandas · error · ValueError
Cannot modify read-only array
Error message
Cannot modify read-only array
What it means
Raised by ExtensionArray.__setitem__ when `self._readonly` is True. Several immutable extension arrays (and views flagged readonly after slicing/astype-is-view operations) set _readonly to prevent in-place mutation; any assignment via `arr[i] = value` (including internal use by Series.where on a copy) then raises ValueError. The check runs before any subclass-specific __setitem__ logic.
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 71959b8cb9)
Solutions
- Force a writable copy before assigning: `s = s.copy(); s.iloc[i] = v`.
- Avoid in-place mutation of slices/views; rebuild with pd.concat/where instead.
- Check `s.array._readonly` (or equivalent) before attempting mutation.
- Use functional updates: `s = s.mask(cond, new_value)` rather than item assignment.
Example fix
# before
s = pd.Series([1,2,3], dtype="Int64")
view = s.astype("Int64") # may be readonly view
view.iloc[0] = 99 # ValueError: Cannot modify read-only array
# after
view = s.astype("Int64").copy()
view.iloc[0] = 99 Defensive patterns
Strategy: validation
Validate before calling
def safe_setitem(arr, key, value):
if getattr(arr, "_readonly", False):
arr = arr.copy()
arr[key] = value
return arr Type guard
def is_readonly(arr) -> bool:
return bool(getattr(arr, "_readonly", False)) Try / catch
try:
arr[key] = value
except ValueError as e:
if "read-only" in str(e):
arr = arr.copy()
arr[key] = value
else:
raise Prevention
- Call .copy() before mutating views produced by astype/slicing.
- Prefer functional updates (mask/where/replace) over item assignment.
- Check array._readonly in helper functions that accept arbitrary extension arrays.
When it happens
Trigger: Calling `arr[i] = v` or `s.iloc[i] = v` on an immutable extension array (e.g. some ArrowExtensionArray views, categorical copies marked readonly, or arrays explicitly flagged readonly). Triggered internally when pandas tries to use __setitem__ on a readonly view produced by astype/slicing.
Common situations: Mutating a Series that was created from a readonly view; chaining astype followed by in-place assignment; libraries handing pandas readonly buffers; categorical/date arrays marked immutable.
Related errors
- {type(self)} does not implement __setitem__.
- Cannot modify read-only array
- cannot diff {type(arr).__name__} on axis={axis}
- {type(arr).__name__} has no 'diff' method. Convert to a suit
- Column {colname} is backed by an extension array, which is n
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/82ff92e4acd21bb8.
Report an issue: GitHub.