pandas-dev/pandas · error · ValueError
Cannot cast NaN value to Integer dtype.
Error message
Cannot cast NaN value to Integer dtype.
What it means
Raised by _coerce_to_data_and_mask when constructing an integer nullable dtype (Int8/16/32/64, UInt8/16/32/64) from float data that contains NaN, but only when the is_nan_na() config option is False (the default). With default NA semantics, np.nan is NOT treated as a missing-value marker for nullable integers, so it cannot be stored in an integer column. This guard prevents silent lossy conversion of NaN into an integer slot.
Solutions
- Replace np.nan with pd.NA before casting: df['col'] = df['col'].replace({np.nan: pd.NA}).astype('Int64').
- Keep the column as Float64 (which accepts np.nan/pd.NA) if integer semantics are not required.
- Drop or impute the NaN rows before the integer cast: df.dropna(subset=['col']).astype('Int64').
- Enable NaN-as-NA globally via pd.set_option('mode.nan_as_na', True) (changes library-wide NA semantics — use with care).
Example fix
# before pd.array([1.0, np.nan], dtype='Int64') # raises # after pd.array([1.0, pd.NA], dtype='Int64')
Defensive patterns
Strategy: validation
Validate before calling
import numpy as np
import pandas as pd
def cast_to_int_nullable(series):
if series.dtype.kind == 'f' and series.isna().any():
# np.nan isn't NA for Int dtypes by default
series = series.replace({np.nan: pd.NA})
return series.astype('Int64') Type guard
def has_numpy_nan(series) -> bool:
import numpy as np
return series.dtype.kind == 'f' and bool(np.isnan(series.to_numpy()).any()) Try / catch
try:
s.astype('Int64')
except ValueError as e:
if 'Cannot cast NaN' in str(e):
s = s.replace({np.nan: pd.NA}).astype('Int64')
else:
raise Prevention
- Standardize on pd.NA (not np.nan) as the missing marker for nullable-integer pipelines.
- When reading float data, replace np.nan with pd.NA before casting to Int/UInt.
- Keep float columns as Float64 if you need to preserve np.nan semantics.
When it happens
Trigger: pd.array([1.0, np.nan], dtype='Int64'); df['col'] = df['col'].astype('Int64') where col is float64 containing np.nan; pd.Series([1.0, float('nan')], dtype='UInt32'). The check is gated on dtype_cls name starting with 'I' or 'U' and is_nan_na() being False.
Common situations: Reading float data with np.nan sentinels and trying to cast to nullable Int; mixing np.nan (float NA) with pd.NA semantics; upstream code that uses np.nan as its missing marker.
Related errors
- cannot convert float NaN to integer
- FloatingArray does not support np.float16 dtype.
- mask must be a 1D list-like
- values must be a 1D list-like
- values should be numpy array. Use the 'pd.array' function…
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/2def657be00eafdc.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/numeric.py:204
if values.ndim != 1:
raise TypeError("values must be a 1D list-like")
if mask is None:
if values.dtype.kind in "iu":
# fastpath
mask = np.zeros(len(values), dtype=np.bool_)
elif values.dtype.kind == "f":
# np.isnan is faster than is_numeric_na() for floats
# github issue: #60066
if is_nan_na():
mask = np.isnan(values)
else:
mask = np.zeros(len(values), dtype=np.bool_)
if dtype_cls.__name__.strip("_").startswith(("I", "U")):
wrong = np.isnan(values)
if wrong.any():
raise ValueError("Cannot cast NaN value to Integer dtype.")
elif is_nan_na():
mask = libmissing.is_numeric_na(values)
else:
# is_numeric_na will raise on non-numeric NAs
libmissing.is_numeric_na(values)
mask = libmissing.is_pdna_or_none(values)
else:
assert len(mask) == len(values)
if mask.ndim != 1:
raise TypeError("mask must be a 1D list-like")
# infer dtype if needed
if dtype is None:
dtype = default_dtype
else:
dtype = dtype.numpy_dtype
View on GitHub (pinned to 3b7651241d)