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

Raised by validate_putmask (putmask.py:110) as a ValueError when the boolean mask passed to a putmask/where operation has a different shape than the target values array. Before any assignment pandas validates mask.shape == values.shape so the boolean selection stays positional and unambiguous; a shape mismatch (including wrong number of dims) is rejected immediately.

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 71959b8cb9)

Solutions

  1. Ensure mask has the same shape as values: reshape/broadcast first, e.g. mask = mask.reshape(df.shape) or use a column-aligned boolean Series.
  2. Construct the mask from the frame itself so shapes stay aligned: mask = df > 0.
  3. If masking a single column, select it first: df['col'].where(mask, other).

Example fix

// before
df = pd.DataFrame({'a':[1,2],'b':[3,4]})
df.where([True, False], other=0)  # 1-D mask on 2-D frame
// after
df.where(pd.DataFrame([[True,False],[True,False]], columns=df.columns), other=0)
// or per-column
df['a'].where([True, False], other=0)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
mask_arr = np.asarray(mask)
if mask_arr.shape != np.asarray(values).shape:
    raise ValueError(f'mask shape {mask_arr.shape} != values shape {np.asarray(values).shape}')

Type guard

def putmask_shape_matches(values, mask) -> bool:
    import numpy as np
    return np.asarray(mask).shape == np.asarray(values).shape

Try / catch

try:
    df.where(mask, other=other)
except ValueError as e:
    if 'mask and data must be the same size' in str(e):
        df.where(np.broadcast_to(mask, df.shape), other=other)
    else:
        raise

Prevention

When it happens

Trigger: df.where(mask, ...) where mask is a 1-D array applied to a 2-D frame, or a 2-D mask applied to a 1-D Series; mask built from a different column or a differently-indexed Series that wasn't broadcast; mask from np.random with the wrong size. Hit at putmask.py:108-110 when mask.shape != values.shape.

Common situations: Applying a per-column mask to a whole frame without broadcasting; mismatched shapes after a transpose; mask computed on a subset and not realigned; passing a list of booleans whose length differs from the data.

Related errors


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