{"record":{"id":"ac7c4422e6ba3d22","repo":"pandas-dev/pandas","slug":"cannot-mask-with-non-boolean-array-containing-na","errorCode":null,"errorMessage":"Cannot mask with non-boolean array containing NA / NaN values","messagePattern":"Cannot mask with non-boolean array containing NA / NaN values","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/common.py","lineNumber":151,"sourceCode":"\n    See Also\n    --------\n    check_array_indexer : Check that `key` is a valid array to index,\n        and convert to an ndarray.\n    \"\"\"\n    if isinstance(\n        key,\n        (ABCSeries, np.ndarray, ABCIndex, ABCExtensionArray, ABCNumpyExtensionArray),\n    ) and not isinstance(key, ABCMultiIndex):\n        if key.dtype == np.object_:\n            key_array = np.asarray(key)\n\n            if not lib.is_bool_array(key_array):\n                na_msg = \"Cannot mask with non-boolean array containing NA / NaN values\"\n                if lib.is_bool_array(key_array, skipna=True):\n                    # Don't raise on e.g. [\"A\", \"B\", np.nan], see\n                    #  test_loc_getitem_list_of_labels_categoricalindex_with_na\n                    raise ValueError(na_msg)\n                return False\n            return True\n        elif is_bool_dtype(key.dtype):\n            return True\n    elif isinstance(key, list):\n        # check if np.array(key).dtype would be bool\n        if len(key) > 0:\n            if type(key) is not list:\n                # GH#42461 cython will raise TypeError if we pass a subclass\n                key = list(key)\n            return lib.is_bool_list(key)\n\n    return False\n\n\ndef cast_scalar_indexer(val: Any) -> Any:\n    \"\"\"\n    Disallow indexing with a float key, even if that key is a round number.","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/common.py#L133-L169","documentation":"Raised in pandas/core/common.py:151 within the boolean-mask validation used by __getitem__/loc when a mask array of object dtype contains NA/NaN among non-boolean entries. The guard distinguishes a pure boolean mask (ok) from a mask that mixes booleans and NaN, which is ambiguous and cannot safely select rows.","triggerScenarios":"`df[mask]` or `df.loc[mask]` where `mask` is an object-dtype array/Series containing values like [True, False, np.nan, True]. Commonly arises from elementwise comparisons on object columns, or a Series of booleans with missing values, or a list with NaN.","commonSituations":"Comparing object/nullable columns producing NaN (e.g. `df['x'] == 'a'` where x has NaN), boolean masks built via `np.where` without a fillna, or masks derived from joins/groupby that introduce NaN alignment.","solutions":["Fill the mask's missing values before indexing: `df[mask.fillna(False)]` or `mask.astype('boolean').fillna(False)`.","Use pandas nullable boolean dtype: convert with `.astype('boolean')` which has a native NA, then decide True/False explicitly.","Recompute the mask so NaN compares to False: `df['x'].eq('a', fill_value=False)` or `df['x'].fillna('').eq('a')`."],"exampleFix":"# before\nmask = df['x'] == 'a'   # object column -> NaN where x is NaN\ndf[mask]\n\n# after\ndf[df['x'].fillna('').eq('a')]","handlingStrategy":"validation","validationCode":"import numpy as np\n\ndef clean_boolean_mask(mask):\n    arr = np.asarray(mask)\n    if arr.dtype == object or arr.dtype.kind == 'O':\n        return np.array([bool(x) if x is not np.nan else False for x in arr], dtype=bool)\n    return arr.astype(bool)\n\ndf[clean_boolean_mask(mask)]","typeGuard":"import numpy as np\n\ndef is_clean_bool_mask(mask) -> bool:\n    arr = np.asarray(mask)\n    return arr.dtype == bool or (arr.dtype == object and not np.isnan(arr).any())","tryCatchPattern":"try:\n    sub = df[mask]\nexcept ValueError as e:\n    if 'Cannot mask with non-boolean' in str(e):\n        mask = mask.fillna(False) if hasattr(mask, 'fillna') else mask\n        sub = df[mask]\n    else:\n        raise","preventionTips":["fillna(False) boolean masks derived from object/nullable columns before indexing.","Use the nullable 'boolean' dtype for masks that may contain NA.","Prefer .eq/.ne with fill_value to avoid NaN propagation in comparisons."],"tags":["boolean-mask","na-nan","indexing","loc","valueerror"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}