{"record":{"id":"98cb6ed96aecc210","repo":"python/cpython","slug":"cannot-convert-nan-to-integer","errorCode":null,"errorMessage":"Cannot convert NaN to integer","messagePattern":"Cannot convert NaN to integer","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydecimal.py","lineNumber":1580,"sourceCode":"        if other is NotImplemented:\n            return other\n        return other.__floordiv__(self, context=context)\n\n    def __float__(self):\n        \"\"\"Float representation.\"\"\"\n        if self._isnan():\n            if self.is_snan():\n                raise ValueError(\"Cannot convert signaling NaN to float\")\n            s = \"-nan\" if self._sign else \"nan\"\n        else:\n            s = str(self)\n        return float(s)\n\n    def __int__(self):\n        \"\"\"Converts self to an int, truncating if necessary.\"\"\"\n        if self._is_special:\n            if self._isnan():\n                raise ValueError(\"Cannot convert NaN to integer\")\n            elif self._isinfinity():\n                raise OverflowError(\"Cannot convert infinity to integer\")\n        s = (-1)**self._sign\n        if self._exp >= 0:\n            return s*int(self._int)*10**self._exp\n        else:\n            return s*int(self._int[:self._exp] or '0')\n\n    __trunc__ = __int__\n\n    @property\n    def real(self):\n        return self\n\n    @property\n    def imag(self):\n        return Decimal(0)\n","sourceCodeStart":1562,"sourceCodeEnd":1598,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydecimal.py#L1562-L1598","documentation":"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.","triggerScenarios":"int(Decimal('NaN')); int(Decimal('-sNaN')) (any NaN); math.trunc(Decimal('NaN')); int(row['qty']) where qty parsed as NaN.","commonSituations":"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.","solutions":["Pre-check value.is_nan() and substitute a policy value (0) or skip the row","Treat missing data as its own case at parse time instead of NaN sentinel","Use int(value.to_integral_value(rounding=ROUND_DOWN)) only for finite values — it still fails on NaN, so the guard is what matters"],"exampleFix":"// before\nn = int(qty)  # ValueError when qty is Decimal('NaN')\n\n// after\nn = 0 if qty.is_nan() else int(qty)","handlingStrategy":"validation","validationCode":"def safe_int(d, default=0):\n    if d.is_nan():\n        return default\n    return int(d)","typeGuard":"def is_int_convertible(d) -> bool:\n    return not d._is_special","tryCatchPattern":"try:\n    n = int(d)\nexcept ValueError:\n    n = 0  # NaN policy\nexcept OverflowError:\n    raise OverflowError(f'{d} overflowed int conversion') from None","preventionTips":["One _is_special guard covers both int() failure modes (NaN -> ValueError, Inf -> OverflowError)","Do not rely on truthiness: bool(Decimal('NaN')) is True","Parse missing CSV/JSON fields to a sentinel you control, not Decimal('NaN')"],"tags":["decimal","int-conversion","nan","truncation","valueerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}