{"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/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/datetimelike.py#L720-L756","documentation":"Raised in DatetimeLikeArrayMixin.fillna when copy=False and the underlying ndarray is flagged read-only (self._readonly is True). fillna with an in-place scalar fill reuses self._ndarray to avoid a copy, but writing into a read-only buffer is illegal in numpy, so pandas raises ValueError before attempting the write.","triggerScenarios":"Calling arr.fillna(value, copy=False) or df[col].fillna(value, inplace=True) on a column backed by a read-only buffer — typically an array created from a numpy read-only array (e.g. np.frombuffer, a memory-mapped array, or an array slice marked WRITEABLE=False), or a block shared from a frame that was constructed without copying.","commonSituations":"Memory-mapped datasets (np.memmap), arrays produced by np.asarray(buf) where buf is immutable, zero-copy slicing of a parent frame that was itself marked read-only; calling .fillna(inplace=True) on such a column.","solutions":["Call fillna with copy=True (the default) so a writable copy is made before writing.","If you must mutate in place, first make the buffer writable: arr = arr.copy() or np.asarray(arr).setflags(write=True) before fillna.","Locate where the read-only flag was set (often an upstream np.frombuffer/memmap) and copy at that boundary instead."],"exampleFix":"// before\narr.fillna(pd.NaT, copy=False)  # ValueError if arr is read-only\n\n// after\narr = arr.copy()\narr.fillna(pd.NaT, copy=False)","handlingStrategy":"validation","validationCode":"import numpy as np\n\ndef safe_fillna(arr, value, copy=False):\n    if not copy:\n        try:\n            writable = arr._ndarray.flags.writeable\n        except AttributeError:\n            writable = True\n        if not writable:\n            arr = arr.copy()\n    return arr.fillna(value, copy=copy)","typeGuard":"import numpy as np\n\ndef is_writable(arr) -> bool:\n    nd = getattr(arr, '_ndarray', None)\n    return nd is None or nd.flags.writeable","tryCatchPattern":"try:\n    arr.fillna(value, copy=False)\nexcept ValueError as e:\n    if 'read-only' in str(e):\n        arr = arr.copy()\n        arr.fillna(value, copy=False)\n    else:\n        raise","preventionTips":["Default to copy=True for fillna on arrays sourced from buffers/memmaps/frombuffer.","Copy at the boundary where read-only buffers enter your pipeline (np.asarray(x).copy()).","Avoid inplace=True fillna on columns from zero-copy slices."],"tags":["datetime","readonly","fillna","numpy","value-error"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}