{"record":{"id":"63f6255712af0015","repo":"pandas-dev/pandas","slug":"cannot-modify-read-only-array","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/_mixins.py","lineNumber":243,"sourceCode":"        # override base class by adding axis keyword\n        validate_bool_kwarg(skipna, \"skipna\")\n        if not skipna and self._hasna:\n            raise ValueError(\"Encountered an NA value with skipna=False\")\n        return nargminmax(self, \"argmax\", axis=axis)\n\n    def unique(self) -> Self:\n        new_data = unique(self._ndarray)\n        return self._from_backing_data(new_data)\n\n    def sort(\n        self,\n        *,\n        ascending: bool = True,\n        kind: SortKind = \"quicksort\",\n        na_position: str = \"last\",\n    ) -> None:\n        if self._readonly:\n            raise ValueError(\"Cannot modify read-only array\")\n        sort_indices = self.argsort(\n            ascending=ascending, kind=kind, na_position=na_position\n        )\n        self._ndarray[:] = self._ndarray[sort_indices]\n\n    @classmethod\n    def _concat_same_type(\n        cls,\n        to_concat: Sequence[Self],\n        axis: AxisInt = 0,\n    ) -> Self:\n        \"\"\"\n        Concatenate multiple arrays of this dtype.\n\n        Parameters\n        ----------\n        to_concat : sequence of this type\n","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/_mixins.py#L225-L261","documentation":"`ValueError('Cannot modify read-only array')` raised by the in-place `sort()` method of `NDArrayBackedExtensionArray`. pandas marks arrays that are views onto immutable storage (e.g. blocks shared from another array, or arrays explicitly flagged) with `self._readonly = True`; an in-place reordering would mutate memory the array does not own. The guard fires before `self._ndarray[:] = self._ndarray[sort_indices]`.","triggerScenarios":"Calling `.sort(...)` (the EA-level in-place sort) — or the public paths that delegate to it — on an array that pandas has flagged read-only. Commonly reached when sorting a Series/Index whose underlying block is a view, or after operations that hand back a read-only backing array.","commonSituations":"Operating on a Series/Index that shares memory with a DataFrame block pandas froze; chaining `.sort_values(inplace=True)` style operations; receiving an EA from an internal API that sets `_readonly` for copy-on-write safety.","solutions":["Sort out-of-place instead: `arr.sort_values()` / `Series.sort_values()` return a new object.","Operate on an explicit copy: `arr = arr.copy(); arr.sort(...)`.","If you built the array yourself, ensure it owns its ndarray (do not set `_readonly=True`) before in-place mutation."],"exampleFix":"// before\narr.sort(...)   # arr._readonly is True -> ValueError\n\n// after\narr = arr.copy()\narr.sort(...)\n# or simply\nsorted_arr = arr[axt.argsort(...)]","handlingStrategy":"validation","validationCode":"if getattr(arr, '_readonly', False):\n    arr = arr.copy()\narr.sort(...)","typeGuard":"def is_mutable(arr) -> bool:\n    return not getattr(arr, '_readonly', False)","tryCatchPattern":"try:\n    arr.sort(...)\nexcept ValueError as e:\n    if 'read-only' in str(e):\n        arr = arr.copy()\n        arr.sort(...)\n    else:\n        raise","preventionTips":["Prefer out-of-place sorts (sort_values) under copy-on-write","Copy before any in-place mutation on arrays you do not own"],"tags":["read-only","sort","copy-on-write","mutation"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}