pandas-dev/pandas · error · ValueError
Cannot modify read-only array
Error message
Cannot modify read-only array
What it means
Raised by DatetimeLikeArrayMixin.fillna when copy=False is requested but the backing ndarray is marked read-only (self._readonly is True). Pandas cannot fill NaT sentinels in-place into memory it is not permitted to write to, so it refuses rather than silently producing a wrong result. The error is a ValueError, not a TypeError, because the inputs are otherwise valid.
Source
Thrown at pandas/core/arrays/datetimelike.py:738
self._check_compatible_with(other)
other = other._ndarray
return other
def fillna(self, value, limit: int | None = None, copy: bool = True) -> Self:
# Fast path: single-pass Cython using iNaT sentinel. GH#42147
if lib.is_scalar(value):
if not self._hasna:
return self.copy() if copy else self[:]
try:
validated = self._validate_setitem_value(value)
except (ValueError, TypeError):
pass
else:
if copy:
new_ndarray = self._ndarray.copy()
else:
if self._readonly:
raise ValueError("Cannot modify read-only array")
new_ndarray = self._ndarray
arr_i8 = new_ndarray.view("i8")
fill_i8 = np.array(validated, dtype=new_ndarray.dtype).view("i8")[()]
algos.scalar_fillna_inplace(
arr_i8, fill_i8, is_datetimelike=True, limit=limit
)
return type(self)._simple_new(new_ndarray, dtype=self.dtype)
return super().fillna(value, limit=limit, copy=copy)
# ------------------------------------------------------------------
# Additional array methods
# These are not part of the EA API, but we implement them because
# pandas assumes they're there.
@ravel_compatView on GitHub (pinned to 71959b8cb9)
Solutions
- Drop the copy=False argument so fillna allocates a fresh writable array (default copy=True).
- Make the backing buffer writable before the call: arr = s.array._ndarray; arr.flags.writeable = True (or copy it with arr.copy()).
- If you must avoid a copy, call the non-inplace path explicitly: s.fillna(value) and reassign, then operate on the result.
- Audit upstream code that produced the read-only array (mmap, np.frombuffer, pyarrow) and either copy at ingestion time or set writeable=True there.
Example fix
// before
s.fillna(pd.Timestamp('2020-01-01'), copy=False) # ValueError on read-only backing array
// after
s = s.fillna(pd.Timestamp('2020-01-01')) # copy=True is the default Defensive patterns
Strategy: validation
Validate before calling
arr = s.array._ndarray
if not arr.flags.writeable and s.isna().any():
# fillna(copy=False) will fail; force a copy
s = s.fillna(some_value) # default copy=True Type guard
def is_writable_datetimelike(s) -> bool:
from pandas.api.types import is_datetime64_any_dtype, is_timedelta64_dtype
backing = getattr(s.array, '_ndarray', None)
return (
(is_datetime64_any_dtype(s.dtype) or is_timedelta64_dtype(s.dtype))
and backing is not None
and bool(backing.flags.writeable)
) Try / catch
try:
s.fillna(value, copy=False)
except ValueError as e:
if 'read-only array' in str(e):
s = s.fillna(value) # fall back to copy=True
else:
raise Prevention
- Default to copy=True (omit the keyword) when calling fillna on datetimelike arrays.
- When ingesting from mmap/pyarrow/np.frombuffer, call .copy() once to obtain a writable buffer.
- Assert arr.flags.writeable before inplace mutations.
When it happens
Trigger: Calling s.fillna(value, copy=False) or s.interpolate(...) on a DatetimeIndex/TimedeltaIndex/PeriodIndex whose underlying _ndarray was allocated read-only (e.g. produced via np.frombuffer, memoryview, mmap, or a view of another array's const segment). The fast Cython scalar-fillna path at datetimelike.py:734-747 is entered only when value is scalar and self._hasna is True; inside it, the self._readonly guard at line 737 fires.
Common situations: Interoperating with Arrow/Parquet zero-copy buffers, numpy arrays created with writeable=False, shared-memory or mmap-backed Series, and tests that freeze writability. Also seen after operations that return views (e.g. .iloc without copy) combined with the copy=False keyword on older pandas where the readonly flag was not stripped.
Related errors
- No accumulation for {func} implemented on BaseMaskedArray
- Cannot modify read-only array
- ExtensionArray.fillna does not support filling with a dict.
- Length of 'value' does not match. Got ({len(value)}) expect
- Invalid value '{value!s}' for dtype '{self.dtype}'
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/52ba564d945c18e0.
Report an issue: GitHub.