pandas-dev/pandas · error · ValueError

Cannot modify read-only array

Error message

Cannot modify read-only array

What it means

StringArray.__setitem__ checks the _readonly flag at the top and raises ValueError if the array is read-only. Read-only state is set when the underlying ndarray has writeable=False (e.g., from np.frombuffer, memory mapping, or explicit flags.writeable=False) or when the array is a view into protected memory.

Source

Thrown at pandas/core/arrays/string_.py:871

            value = extract_array(value, extract_numpy=True)
            if not is_array_like_deprecate_non_pandas(value):
                value = np.asarray(value, dtype=object)
            elif isinstance(value.dtype, type(self.dtype)):
                return value
            else:
                # cast categories and friends to arrays to see if values are
                # compatible, compatibility with arrow backed strings
                value = np.asarray(value)
            if len(value) and not lib.is_string_array(value, skipna=True):
                raise TypeError(
                    "Invalid value for dtype 'str'. Value should be a "
                    "string or missing value (or array of those)."
                )
        return value

    def __setitem__(self, key, value) -> None:
        if self._readonly:
            raise ValueError("Cannot modify read-only array")

        value = self._validate_setitem_value(value)

        key = check_array_indexer(self, key)
        scalar_key = lib.is_scalar(key)
        scalar_value = lib.is_scalar(value)
        if scalar_key and not scalar_value:
            raise ValueError("setting an array element with a sequence.")

        if not scalar_value:
            if value.dtype == self.dtype:
                value = value._ndarray
            else:
                value = np.asarray(value)
                mask = isna(value)
                if mask.any():
                    value = value.copy()
                    value[isna(value)] = self.dtype.na_value

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Copy the array before mutating: arr = arr.copy().
  2. Avoid setting arr.flags.writeable = False on arrays you intend to modify.
  3. Detect read-only state up front and branch to a copy path.

Example fix

// before
readonly_arr[0] = 'x'

// after
arr = readonly_arr.copy()
arr[0] = 'x'
Defensive patterns

Strategy: validation

Validate before calling

if getattr(string_array, '_readonly', False):
    string_array = string_array.copy()
string_array[i] = 'x'

Type guard

def is_writable(arr) -> bool:
    return not getattr(arr, '_readonly', False)

Prevention

When it happens

Trigger: Calling string_array[i] = 'x' on an array whose _readonly is True, e.g., one created from a memory-mapped buffer, a zero-copy slice of a read-only buffer, or after arr.flags.writeable = False on the backing ndarray.

Common situations: Loading data via mmap or shared memory; operating on arrays returned by libraries that mark buffers read-only; defensive copies omitted in a pipeline.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/5d02ab71742ccb47. Report an issue: GitHub.