python/cpython · error · ValueError

Cannot convert NaN to integer

Error message

Cannot convert NaN to integer

What it means

int(Decimal('NaN')) (and Decimal('NaN').__trunc__(), which aliases __int__) raises ValueError because NaN has no integer value to truncate to. Infinity raises OverflowError in the adjacent branch; only finite decimals convert.

Source

Thrown at Lib/_pydecimal.py:1580

        if other is NotImplemented:
            return other
        return other.__floordiv__(self, context=context)

    def __float__(self):
        """Float representation."""
        if self._isnan():
            if self.is_snan():
                raise ValueError("Cannot convert signaling NaN to float")
            s = "-nan" if self._sign else "nan"
        else:
            s = str(self)
        return float(s)

    def __int__(self):
        """Converts self to an int, truncating if necessary."""
        if self._is_special:
            if self._isnan():
                raise ValueError("Cannot convert NaN to integer")
            elif self._isinfinity():
                raise OverflowError("Cannot convert infinity to integer")
        s = (-1)**self._sign
        if self._exp >= 0:
            return s*int(self._int)*10**self._exp
        else:
            return s*int(self._int[:self._exp] or '0')

    __trunc__ = __int__

    @property
    def real(self):
        return self

    @property
    def imag(self):
        return Decimal(0)

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pre-check value.is_nan() and substitute a policy value (0) or skip the row
  2. Treat missing data as its own case at parse time instead of NaN sentinel
  3. Use int(value.to_integral_value(rounding=ROUND_DOWN)) only for finite values — it still fails on NaN, so the guard is what matters

Example fix

// before
n = int(qty)  # ValueError when qty is Decimal('NaN')

// after
n = 0 if qty.is_nan() else int(qty)
Defensive patterns

Strategy: validation

Validate before calling

def safe_int(d, default=0):
    if d.is_nan():
        return default
    return int(d)

Type guard

def is_int_convertible(d) -> bool:
    return not d._is_special

Try / catch

try:
    n = int(d)
except ValueError:
    n = 0  # NaN policy
except OverflowError:
    raise OverflowError(f'{d} overflowed int conversion') from None

Prevention

When it happens

Trigger: int(Decimal('NaN')); int(Decimal('-sNaN')) (any NaN); math.trunc(Decimal('NaN')); int(row['qty']) where qty parsed as NaN.

Common situations: CSV/JSON ingestion where missing values parse as Decimal('NaN'), then len/count math does int() on them; bool(NaN) is True so truthiness checks do not filter it out.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/98cb6ed96aecc210. Report an issue: GitHub.