pandas-dev/pandas · error · ValueError

putmask: mask and data must be the same size

Error message

putmask: mask and data must be the same size

What it means

ValueError raised in validate_putmask when the boolean mask's shape differs from the values array's shape. putmask requires element-wise correspondence between mask and data; misaligned shapes (different length or axes) are rejected before any assignment.

Solutions

  1. Reindex the mask to the data's axes: mask = mask.reindex_like(df).
  2. Recompute the mask on the same object you are masking.
  3. Convert the mask and data to the same shape (e.g. Series.to_numpy() on matching index) before assignment.

Example fix

# before
df.where(other_mask, 0)  # other_mask.shape != df.shape
# after
df.where(other_mask.reindex_like(df).fillna(False).to_numpy(), 0)
Defensive patterns

Strategy: validation

Validate before calling

def safe_putmask(df, mask, value):
    if hasattr(mask, 'shape') and mask.shape != df.shape:
        mask = mask.reindex_like(df).fillna(False).to_numpy()
    return df.where(mask, value)

Try / catch

try:
    df.where(mask, value)
except ValueError as e:
    if 'mask and data must be the same size' in str(e):
        df.where(mask.reindex_like(df).fillna(False).to_numpy(), value)
    else:
        raise

Prevention

When it happens

Trigger: df.where(other_df_mask, value) where other_df_mask has different rows/columns; Series.where(series_mask_of_different_len, value); np.putmask-style calls reached internally with an unaligned mask.

Common situations: Reusing a mask computed on a filtered/resampled frame against the original frame without realigning.

Related errors


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

Appendix: source

Thrown at pandas/core/array_algos/putmask.py:110

            np.place(values, mask, new)
            # i.e. values[mask] = new
        elif mask.shape[-1] == shape[-1] or shape[-1] == 1:
            np.putmask(values, mask, new)
        else:
            raise ValueError("cannot assign mismatch length to masked array")
    else:
        np.putmask(values, mask, new)


def validate_putmask(
    values: ArrayLike | MultiIndex, mask: np.ndarray
) -> tuple[npt.NDArray[np.bool_], bool]:
    """
    Validate mask and check if this putmask operation is a no-op.
    """
    mask = extract_bool_array(mask)
    if mask.shape != values.shape:
        raise ValueError("putmask: mask and data must be the same size")

    noop = not mask.any()
    return mask, noop


def extract_bool_array(mask: ArrayLike) -> npt.NDArray[np.bool_]:
    """
    If we have a SparseArray or BooleanArray, convert it to ndarray[bool].
    """
    if isinstance(mask, ExtensionArray):
        # We could have BooleanArray, Sparse[bool], ...
        #  Except for BooleanArray, this is equivalent to just
        #  np.asarray(mask, dtype=bool)
        mask = mask.to_numpy(dtype=bool, na_value=False)

    mask = np.asarray(mask, dtype=bool)
    return mask

View on GitHub (pinned to 3b7651241d)