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

  1. Replace np.nan with pd.NA before casting: df['col'] = df['col'].replace({np.nan: pd.NA}).astype('Int64').
  2. Keep the column as Float64 (which accepts np.nan/pd.NA) if integer semantics are not required.
  3. Drop or impute the NaN rows before the integer cast: df.dropna(subset=['col']).astype('Int64').
  4. 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

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


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)