{"record":{"id":"f39a35db80433df7","repo":"pandas-dev/pandas","slug":"putmask-mask-and-data-must-be-the-same-size","errorCode":null,"errorMessage":"putmask: mask and data must be the same size","messagePattern":"putmask: mask and data must be the same size","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/array_algos/putmask.py","lineNumber":110,"sourceCode":"            np.place(values, mask, new)\n            # i.e. values[mask] = new\n        elif mask.shape[-1] == shape[-1] or shape[-1] == 1:\n            np.putmask(values, mask, new)\n        else:\n            raise ValueError(\"cannot assign mismatch length to masked array\")\n    else:\n        np.putmask(values, mask, new)\n\n\ndef validate_putmask(\n    values: ArrayLike | MultiIndex, mask: np.ndarray\n) -> tuple[npt.NDArray[np.bool_], bool]:\n    \"\"\"\n    Validate mask and check if this putmask operation is a no-op.\n    \"\"\"\n    mask = extract_bool_array(mask)\n    if mask.shape != values.shape:\n        raise ValueError(\"putmask: mask and data must be the same size\")\n\n    noop = not mask.any()\n    return mask, noop\n\n\ndef extract_bool_array(mask: ArrayLike) -> npt.NDArray[np.bool_]:\n    \"\"\"\n    If we have a SparseArray or BooleanArray, convert it to ndarray[bool].\n    \"\"\"\n    if isinstance(mask, ExtensionArray):\n        # We could have BooleanArray, Sparse[bool], ...\n        #  Except for BooleanArray, this is equivalent to just\n        #  np.asarray(mask, dtype=bool)\n        mask = mask.to_numpy(dtype=bool, na_value=False)\n\n    mask = np.asarray(mask, dtype=bool)\n    return mask\n","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/array_algos/putmask.py#L92-L128","documentation":"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.","triggerScenarios":"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.","commonSituations":"Reusing a mask computed on a filtered/resampled frame against the original frame without realigning.","solutions":["Reindex the mask to the data's axes: mask = mask.reindex_like(df).","Recompute the mask on the same object you are masking.","Convert the mask and data to the same shape (e.g. Series.to_numpy() on matching index) before assignment."],"exampleFix":"# before\ndf.where(other_mask, 0)  # other_mask.shape != df.shape\n# after\ndf.where(other_mask.reindex_like(df).fillna(False).to_numpy(), 0)","handlingStrategy":"validation","validationCode":"def safe_putmask(df, mask, value):\n    if hasattr(mask, 'shape') and mask.shape != df.shape:\n        mask = mask.reindex_like(df).fillna(False).to_numpy()\n    return df.where(mask, value)","typeGuard":null,"tryCatchPattern":"try:\n    df.where(mask, value)\nexcept ValueError as e:\n    if 'mask and data must be the same size' in str(e):\n        df.where(mask.reindex_like(df).fillna(False).to_numpy(), value)\n    else:\n        raise","preventionTips":["Compute masks on the same object you mask, or reindex_like before use.","Assert mask.shape == df.shape in test code before assignment."],"tags":["putmask","where","shape-mismatch","alignment"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}