{"record":{"id":"c0a342510348e725","repo":"python/cpython","slug":"second-argument-to-round-should-be-integral","errorCode":null,"errorMessage":"Second argument to round should be integral","messagePattern":"Second argument to round should be integral","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_pydecimal.py","lineNumber":1837,"sourceCode":"        self.quantize(Decimal('1En')).\n\n        >>> round(Decimal('123.456'), 0)\n        Decimal('123')\n        >>> round(Decimal('123.456'), 2)\n        Decimal('123.46')\n        >>> round(Decimal('123.456'), -2)\n        Decimal('1E+2')\n        >>> with localcontext(ExtendedContext):\n        ...     round(Decimal('-Infinity'), 37)\n        ...     round(Decimal('sNaN123'), 0)\n        Decimal('NaN')\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","sourceCodeStart":1819,"sourceCodeEnd":1855,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydecimal.py#L1819-L1855","documentation":"round(Decimal, n) with a second argument requires n to be an actual int (isinstance check). Even a float with integral value like 2.0 is rejected with TypeError, because n becomes a quantize exponent (10**-n) that must be an exact integer. The one-argument form round(d) has separate NaN/Infinity handling.","triggerScenarios":"round(Decimal('1.234'), 2.0) (float -> TypeError); round(d, numpy.int64(2)) (isinstance(np.int64, int) is False on many builds); round(d, None) is fine (None means one-arg form); round(d, '2').","commonSituations":"Rounding precision coming from user input or config parsed as float ('round to 2.0 decimals'); numpy integers flowing into round(); decimals places computed as float division.","solutions":["Coerce the digit count: round(d, int(ndigits))","Convert numpy integers: round(d, int(np_int))","Parse config precision with int() at load time"],"exampleFix":"// before\nq = round(price, ndigits)  # ndigits=2.0 from config -> TypeError\n\n// after\nq = round(price, int(ndigits))","handlingStrategy":"type-guard","validationCode":"def is_round_ndigits(n) -> bool:\n    return n is None or (isinstance(n, int) and not isinstance(n, bool))\n\n# q = round(d, int(nd)) if nd is not None else round(d)","typeGuard":"def is_int_ndigits(n) -> bool:\n    return isinstance(n, int) and not isinstance(n, bool)","tryCatchPattern":"try:\n    q = round(d, nd)\nexcept TypeError:\n    q = round(d, int(nd))  # if nd was integral-valued float/np integer","preventionTips":["Always int()-cast the digits argument: round(d, int(ndigits))","Cast numpy integers at the boundary: int(np.int64(2))","Parse decimal-place config with int(), never float()"],"tags":["decimal","rounding","round","typeerror","quantize"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}