{"record":{"id":"980abcdc6acb0b73","repo":"pandas-dev/pandas","slug":"cannot-assign-mismatch-length-to-masked-array","errorCode":null,"errorMessage":"cannot assign mismatch length to masked array","messagePattern":"cannot assign mismatch length to masked array","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/array_algos/putmask.py","lineNumber":97,"sourceCode":"    # TODO: this prob needs some better checking for 2D cases\n    nlocs = mask.sum()\n    if nlocs > 0 and is_list_like(new) and getattr(new, \"ndim\", 1) == 1:\n        shape = np.shape(new)\n        # np.shape compat for if setitem_datetimelike_compat\n        #  changed arraylike to list e.g. test_where_dt64_2d\n        if nlocs == shape[-1]:\n            # GH#30567\n            # If length of ``new`` is less than the length of ``values``,\n            # `np.putmask` would first repeat the ``new`` array and then\n            # assign the masked values hence produces incorrect result.\n            # `np.place` on the other hand uses the ``new`` values at it is\n            # to place in the masked locations of ``values``\n            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","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/array_algos/putmask.py#L79-L115","documentation":"Raised by putmask_without_repeat (putmask.py:97) as a ValueError when a list-like `new` value is being applied through a boolean mask but its length matches neither the number of True positions in the mask nor the full length of the values array (nor 1). numpy's np.putmask would silently repeat/truncate, producing wrong results; pandas detects the length mismatch and refuses.","triggerScenarios":"df.where(cond, other=[1,2,3]) or s.mask(cond, other) where len(other) is neither len(values), mask.sum(), nor 1. Hit at putmask.py:80-97 when nlocs > 0, new is 1-D, and nlocs != shape[-1] AND mask.shape[-1] != shape[-1] AND shape[-1] != 1.","commonSituations":"Passing a replacement list sized to a filtered subset rather than the full array; mismatched lengths after a reindex or filter; building `other` from value_counts().index or similar shape-changing ops; using a Series whose index doesn't align with the masked frame.","solutions":["Size `other` to match either the full array length or exactly the number of True positions in the mask.","Pass a scalar instead of a list for a constant replacement: df.where(cond, other=0).","Use df.mask(cond, other) with a same-shaped Series whose index aligns, so pandas can align positions correctly."],"exampleFix":"// before\ns = pd.Series([1,2,3,4])\ns.where([True,False,True,False], other=[99, 88])  # length 2 mismatches\n// after\ns.where([True,False,True,False], other=[99, 88, 99, 88])  # full length\n// or\ns.where([True,False,True,False], other=99)  # scalar","handlingStrategy":"validation","validationCode":"nlocs = int(np.asarray(mask).sum())\nnew_len = len(new) if hasattr(new, '__len__') else 1\nif new_len not in (1, nlocs, len(values)):\n    raise ValueError(f'other has length {new_len}; expected 1, {nlocs}, or {len(values)}')","typeGuard":"def putmask_other_compatible(values, mask, other) -> bool:\n    import numpy as np\n    nlocs = int(np.asarray(mask).sum())\n    if not hasattr(other, '__len__'):\n        return True\n    return len(other) in (1, nlocs, len(values))","tryCatchPattern":"try:\n    df.where(cond, other=other)\nexcept ValueError as e:\n    if 'mismatch length' in str(e):\n        df.where(cond, other=0)  # scalar fallback\n    else:\n        raise","preventionTips":["Size `other` to match the array or the number of True mask positions.","Prefer a scalar replacement when the value is constant."],"tags":["pandas","where","mask","putmask","length-mismatch"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}