{"record":{"id":"ab16a2c3e5edb14c","repo":"RustPython/RustPython","slug":"cannot-round-a-nan","errorCode":null,"errorMessage":"cannot round a NaN","messagePattern":"cannot round a NaN","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydecimal.py","lineNumber":1840,"sourceCode":"        >>> round(Decimal('123.456'), -2)\n        Decimal('1E+2')\n        >>> round(Decimal('-Infinity'), 37)\n        Decimal('NaN')\n        >>> round(Decimal('sNaN123'), 0)\n        Decimal('NaN123')\n\n        \"\"\"\n        if n is not None:\n            # two-argument form: use the equivalent quantize call\n            if not isinstance(n, int):\n                raise TypeError('Second argument to round should be integral')\n            exp = _dec_from_triple(0, '1', -n)\n            return self.quantize(exp)\n\n        # one-argument form\n        if self._is_special:\n            if self.is_nan():\n                raise ValueError(\"cannot round a NaN\")\n            else:\n                raise OverflowError(\"cannot round an infinity\")\n        return int(self._rescale(0, ROUND_HALF_EVEN))\n\n    def __floor__(self):\n        \"\"\"Return the floor of self, as an integer.\n\n        For a finite Decimal instance self, return the greatest\n        integer n such that n <= self.  If self is infinite or a NaN\n        then a Python exception is raised.\n\n        \"\"\"\n        if self._is_special:\n            if self.is_nan():\n                raise ValueError(\"cannot round a NaN\")\n            else:\n                raise OverflowError(\"cannot round an infinity\")\n        return int(self._rescale(0, ROUND_FLOOR))","sourceCodeStart":1822,"sourceCodeEnd":1858,"githubUrl":"https://github.com/RustPython/RustPython/blob/aaeab4f754b4f40efc0c8ab39cf7c4a3c35a8cfd/Lib/_pydecimal.py#L1822-L1858","documentation":"The one-argument round(Decimal) rescales to an integer with ROUND_HALF_EVEN, which is undefined for specials: a NaN raises this ValueError (infinity raises OverflowError). Note round(sNaN, 0) instead routes through quantize and returns a NaN with the diagnostic attached.","triggerScenarios":"round(Decimal('NaN')); round(Decimal('sNaN')); rounding values parsed from strings like 'nan' or produced by 0/0-style operations under non-trapping contexts.","commonSituations":"Rounding user-supplied numeric fields where NaN is a valid token; processing sensor/datafeed NaN sentinels through a rounding step.","solutions":["Gate on finiteness: r = round(d) if d.is_finite() else None.","Reject NaN tokens at parse time so rounding never sees them.","Catch ValueError around round() for untrusted input."],"exampleFix":"# before\nr = round(Decimal(value_str))  # ValueError when value_str == 'nan'\n\n# after\nd = Decimal(value_str)\nr = round(d) if d.is_finite() else None","handlingStrategy":"validation","validationCode":"r = round(d) if d.is_finite() else None","typeGuard":"def roundable_decimal(d):\n    return d.is_finite()","tryCatchPattern":"try:\n    r = round(d)\nexcept ValueError:\n    r = None  # NaN policy","preventionTips":["Filter NaN sentinels before rounding pipelines.","Use is_finite() to cover both ValueError and OverflowError cases.","Prefer round(d, 0) via quantize semantics only when you understand sNaN handling there."],"tags":["python","decimal","valueerror","nan","round"],"backgroundTag":"convert-nan-to-number","analyzedSha":"aaeab4f754b4f40efc0c8ab39cf7c4a3c35a8cfd","analyzedAt":"2026-08-17T00:37:52.100Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}