pandas-dev/pandas · error · ValueError
cannot convert float NaN to bool
Error message
cannot convert float NaN to bool
What it means
Raised by BaseMaskedArray._astype when casting a masked array with missing values to a bool numpy dtype. numpy's astype_nansafe would convert np.nan to True, which is wrong, so pandas refuses up front. A compatible na_value must be supplied (e.g. False) or NAs removed first.
Source
Thrown at pandas/core/arrays/masked.py:808
na_value: float | np.datetime64 | lib.NoDefault
# coerce
if dtype.kind == "f":
# In astype, we consider dtype=float to also mean na_value=np.nan
na_value = np.nan
elif dtype.kind == "M":
unit = np.datetime_data(dtype)[0]
na_value = np.datetime64("NaT", unit) # type: ignore[call-overload]
else:
na_value = lib.no_default
# to_numpy will also raise, but we get somewhat nicer exception messages here
if dtype.kind in "iu" and self._hasna:
raise ValueError("cannot convert NA to integer")
if dtype.kind == "b" and self._hasna:
# careful: astype_nansafe converts np.nan to True
raise ValueError("cannot convert float NaN to bool")
data = self.to_numpy(dtype=dtype, na_value=na_value, copy=copy)
return data
__array_priority__ = 1000 # higher than ndarray so ops dispatch to us
def __array__(
self, dtype: NpDtype | None = None, copy: bool | None = None
) -> np.ndarray:
"""
the array interface, return my values
We return an object array here to preserve our scalar values
"""
if copy is False:
if not self._hasna:
# special case, here we can simply return the underlying data
result = np.array(self._data, dtype=dtype, copy=copy)
# If the ExtensionArray is readonly, make the numpy array readonly tooView on GitHub (pinned to 71959b8cb9)
Solutions
- Drop or impute missing values first: arr.dropna().astype('bool') or arr.fillna(False).astype('bool').
- Convert via to_numpy with an explicit na_value: arr.to_numpy(dtype='bool', na_value=False).
- Use a nullable Boolean dtype if NA must be preserved: arr.astype('boolean').
Example fix
// before s.astype(bool) # raises: cannot convert float NaN to bool // after s.fillna(False).astype(bool)
Defensive patterns
Strategy: validation
Validate before calling
def safe_bool_cast(arr):
if getattr(arr, "_hasna", False):
raise ValueError("array has NA; fill or drop before casting to bool")
return arr.astype(bool) Type guard
def is_na_free(arr) -> bool:
return not getattr(arr, "_hasna", False) Try / catch
try:
out = arr.astype(bool)
except ValueError as e:
if "cannot convert float NaN to bool" in str(e):
out = arr.fillna(False).astype(bool)
else:
raise Prevention
- Fill or drop NAs before any bool cast.
- Use to_numpy(dtype='bool', na_value=False) when a default is acceptable.
- Keep boolean-mask construction behind a tested helper.
When it happens
Trigger: Calling arr.astype('bool') / arr.astype(bool) / np.asarray(arr, dtype=bool) on a BaseMaskedArray that has any missing values.
Common situations: Converting a nullable numeric column to a boolean mask while the column still has NaNs; building a truth array from a nullable Series for indexing.
Related errors
- cannot convert NA to integer
- cannot convert to '{dtype}'-dtype NumPy array with missing v
- Unable to avoid copy while creating an array as requested.
- operator '{op_name}' not implemented for bool dtypes
- searchsorted requires array to be sorted, which is impossibl
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/4caf0ffe893e5593.
Report an issue: GitHub.