pandas-dev/pandas · error · ValueError

Cannot modify read-only array

Error message

Cannot modify read-only array

What it means

Raised by BaseMaskedArray._pad_or_backfill when an in-place fill (copy=False) is requested on an array whose _readonly flag is set. pandas marks sliced/shared masked arrays read-only to prevent mutating buffers aliased by other arrays, so it refuses to run the Cython backfill/pad routine that writes into self._data in place.

Solutions

  1. Pass copy=True (the default) so _pad_or_backfill clones data and mask before writing.
  2. Materialize an independent, writable copy first: arr = arr.copy() then arr.ffill() / arr.bfill().
  3. Avoid requesting in-place fills on views; reassign the result instead of relying on copy=False.

Example fix

// before
arr = parent[start:stop]   # view with _readonly=True
arr._pad_or_backfill(method="ffill", copy=False)  # raises
// after
arr = parent[start:stop].copy()
out = arr._pad_or_backfill(method="ffill", copy=True)
Defensive patterns

Strategy: validation

Validate before calling

if getattr(arr, '_readonly', False):
    arr = arr.copy()
out = arr._pad_or_backfill(method='ffill', copy=True)

Type guard

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

Try / catch

try:
    out = arr._pad_or_backfill(method='ffill', copy=False)
except ValueError as e:
    if 'read-only' in str(e):
        out = arr.copy()._pad_or_backfill(method='ffill', copy=False)
    else:
        raise

Prevention

When it happens

Trigger: Calling arr.ffill(), arr.bfill(), or arr._pad_or_backfill(..., copy=False) on a masked ExtensionArray (Int64, Float64, boolean) that was obtained through a slice/view that propagated _readonly=True, or any array explicitly constructed with read-only buffers.

Common situations: Filling NA values on a Series backed by a slice of a larger masked array; chaining .ffill() after a view-producing operation; libraries that hand back read-only views to enforce immutability; passing copy=False expecting zero-copy behavior.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/0424dd786fe16cdd. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/arrays/masked.py:259

        *,
        method: FillnaOptions,
        limit: int | None = None,
        limit_area: Literal["inside", "outside"] | None = None,
        copy: bool = True,
    ) -> Self:
        mask = self._mask

        if mask.any():
            func = missing.get_fill_func(method, ndim=self.ndim)

            npvalues = self._data.T
            new_mask = mask.T
            if copy:
                npvalues = npvalues.copy()
                new_mask = new_mask.copy()
            else:
                if self._readonly:
                    raise ValueError("Cannot modify read-only array")
                if limit_area is not None:
                    mask = mask.copy()
            func(npvalues, limit=limit, mask=new_mask)

            if limit_area is not None and not mask.all():
                mask = mask.T
                neg_mask = ~mask
                first = neg_mask.argmax()
                last = len(neg_mask) - neg_mask[::-1].argmax() - 1
                if limit_area == "inside":
                    new_mask[:first] |= mask[:first]
                    new_mask[last + 1 :] |= mask[last + 1 :]
                elif limit_area == "outside":
                    new_mask[first + 1 : last] |= mask[first + 1 : last]

            if copy:
                return self._simple_new(npvalues.T, new_mask.T)
            else:

View on GitHub (pinned to 3b7651241d)