pandas-dev/pandas · error · ValueError

cannot convert NA to integer

Error message

cannot convert NA to integer

What it means

Raised by BaseMaskedArray.astype when the target dtype has integer kind ('i','u') and the masked array contains missing values. Integer numpy dtypes have no native NA representation, so conversion would silently lose or wrap the NA; pandas raises a clearer message than letting to_numpy fail.

Solutions

  1. Cast to a nullable integer dtype instead: arr.astype('Int64').
  2. Fill or drop NAs first: arr.fillna(0).astype('int64') or arr.dropna().astype('int64').
  3. Cast to float to let NAs become np.nan: arr.astype('float64').

Example fix

// before
arr = pd.array([1, None, 3], dtype='Int64')
arr.astype('int64')   # raises
// after
arr.fillna(0).astype('int64')
Defensive patterns

Strategy: validation

Validate before calling

if dtype.kind in 'iu' and arr._hasna:
    raise ValueError('Refusing int cast with NA; fill or drop first')
out = arr.astype(dtype)

Type guard

def can_astype_int(arr) -> bool:
    return not arr._hasna

Try / catch

try:
    out = arr.astype('int64')
except ValueError as e:
    if 'NA to integer' in str(e):
        out = arr.fillna(0).astype('int64')
    else:
        raise

Prevention

When it happens

Trigger: Calling arr.astype('int64') or arr.astype(np.int32) on a nullable integer/float/boolean masked array where self._hasna is True.

Common situations: Forcing a nullable Int64 column back to numpy int64 without handling NAs; pipelines that assume no missing data; reads from Parquet/CSV that produced NA where downstream code expects plain ints.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/9fa6f413ca718079. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/arrays/masked.py:805

        if isinstance(dtype, ExtensionDtype):
            eacls = dtype.construct_array_type()
            return eacls._from_sequence(self, dtype=dtype, copy=copy)

        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:

View on GitHub (pinned to 3b7651241d)