pandas-dev/pandas · error · ValueError

cannot assign mismatch length to masked array

Error message

cannot assign mismatch length to masked array

What it means

ValueError raised in putmask (masked assignment) when the new values array cannot be broadcast against the mask locations: the number of mask-true entries does not match the last-axis length of new, and neither the mask nor new is length-1 to allow putmask. pandas refuses to silently repeat or truncate values.

Solutions

  1. Make the replacement scalar so it broadcasts: df.where(mask, 0).
  2. Size replacements to the number of True cells: replacements = replacements[mask.values].
  3. Align the replacement to the frame's full shape and let putmask broadcast.

Example fix

# before
df.where(mask, repl_array)  # len(repl_array) != mask.sum()
# after
df.where(mask, repl_array[mask.to_numpy()])
Defensive patterns

Strategy: validation

Validate before calling

def safe_where(df, mask, replacements):
    import numpy as np
    if not np.isscalar(replacements):
        n_true = int(mask.to_numpy().sum()) if hasattr(mask, 'to_numpy') else int(np.count_nonzero(mask))
        if len(replacements) != n_true:
            raise ValueError(f'replacements length {len(replacements)} != mask true count {n_true}')
    return df.where(mask, replacements)

Try / catch

try:
    df.where(mask, replacements)
except ValueError as e:
    if 'mismatch length' in str(e):
        df.where(mask, replacements[mask.to_numpy()])  # align to true cells
    else:
        raise

Prevention

When it happens

Trigger: df.where(mask, replacements) / df.mask(mask, replacements) / DataFrame.iloc assignment where replacements length != number of True cells; Series.replace via putmask with a mis-sized value array.

Common situations: Building a replacement array from a filtered subset without matching it to the number of masked positions; assigning list/Series values whose length matches the frame but not the mask.

Related errors


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

Appendix: source

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

    # TODO: this prob needs some better checking for 2D cases
    nlocs = mask.sum()
    if nlocs > 0 and is_list_like(new) and getattr(new, "ndim", 1) == 1:
        shape = np.shape(new)
        # np.shape compat for if setitem_datetimelike_compat
        #  changed arraylike to list e.g. test_where_dt64_2d
        if nlocs == shape[-1]:
            # GH#30567
            # If length of ``new`` is less than the length of ``values``,
            # `np.putmask` would first repeat the ``new`` array and then
            # assign the masked values hence produces incorrect result.
            # `np.place` on the other hand uses the ``new`` values at it is
            # to place in the masked locations of ``values``
            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

View on GitHub (pinned to 3b7651241d)