{"record":{"id":"52ba564d945c18e0","repo":"pandas-dev/pandas","slug":"cannot-modify-read-only-array-52ba56","errorCode":null,"errorMessage":"Cannot modify read-only array","messagePattern":"Cannot modify read-only array","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/datetimelike.py","lineNumber":738,"sourceCode":"            self._check_compatible_with(other)\n            other = other._ndarray\n        return other\n\n    def fillna(self, value, limit: int | None = None, copy: bool = True) -> Self:\n        # Fast path: single-pass Cython using iNaT sentinel. GH#42147\n        if lib.is_scalar(value):\n            if not self._hasna:\n                return self.copy() if copy else self[:]\n            try:\n                validated = self._validate_setitem_value(value)\n            except (ValueError, TypeError):\n                pass\n            else:\n                if copy:\n                    new_ndarray = self._ndarray.copy()\n                else:\n                    if self._readonly:\n                        raise ValueError(\"Cannot modify read-only array\")\n                    new_ndarray = self._ndarray\n\n                arr_i8 = new_ndarray.view(\"i8\")\n                fill_i8 = np.array(validated, dtype=new_ndarray.dtype).view(\"i8\")[()]\n                algos.scalar_fillna_inplace(\n                    arr_i8, fill_i8, is_datetimelike=True, limit=limit\n                )\n\n                return type(self)._simple_new(new_ndarray, dtype=self.dtype)\n\n        return super().fillna(value, limit=limit, copy=copy)\n\n    # ------------------------------------------------------------------\n    # Additional array methods\n    #  These are not part of the EA API, but we implement them because\n    #  pandas assumes they're there.\n\n    @ravel_compat","sourceCodeStart":720,"sourceCodeEnd":756,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/datetimelike.py#L720-L756","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ns.fillna(pd.Timestamp('2020-01-01'), copy=False)  # ValueError on read-only backing array\n// after\ns = s.fillna(pd.Timestamp('2020-01-01'))  # copy=True is the default","handlingStrategy":"validation","validationCode":"arr = s.array._ndarray\nif not arr.flags.writeable and s.isna().any():\n    # fillna(copy=False) will fail; force a copy\n    s = s.fillna(some_value)  # default copy=True","typeGuard":"def is_writable_datetimelike(s) -> bool:\n    from pandas.api.types import is_datetime64_any_dtype, is_timedelta64_dtype\n    backing = getattr(s.array, '_ndarray', None)\n    return (\n        (is_datetime64_any_dtype(s.dtype) or is_timedelta64_dtype(s.dtype))\n        and backing is not None\n        and bool(backing.flags.writeable)\n    )","tryCatchPattern":"try:\n    s.fillna(value, copy=False)\nexcept ValueError as e:\n    if 'read-only array' in str(e):\n        s = s.fillna(value)  # fall back to copy=True\n    else:\n        raise","preventionTips":["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."],"tags":["read-only","inplace","fillna","datetimelike"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}