{"id":"8d873abd7dd39eb0","repo":"pytest-dev/pytest","slug":"absolute-tolerance-can-t-be-nan","errorCode":null,"errorMessage":"absolute tolerance can't be NaN.","messagePattern":"absolute tolerance can't be NaN\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/approx.py","lineNumber":565,"sourceCode":"    @property\n    def tolerance(self):\n        \"\"\"Return the tolerance for the comparison.\n\n        This could be either an absolute tolerance or a relative tolerance,\n        depending on what the user specified or which would be larger.\n        \"\"\"\n        # Figure out what the absolute tolerance should be.  ``self.abs`` is\n        # either None or a value specified by the user.\n        absolute_tolerance = (\n            self.abs if self.abs is not None else self.DEFAULT_ABSOLUTE_TOLERANCE\n        )\n\n        if absolute_tolerance < 0:\n            raise ValueError(\n                f\"absolute tolerance can't be negative: {absolute_tolerance}\"\n            )\n        if math.isnan(absolute_tolerance):\n            raise ValueError(\"absolute tolerance can't be NaN.\")\n\n        # If the user specified an absolute tolerance but not a relative one,\n        # just return the absolute tolerance.\n        if self.rel is None:\n            if self.abs is not None:\n                return absolute_tolerance\n\n        # Figure out what the relative tolerance should be.  ``self.rel`` is\n        # either None or a value specified by the user.  This is done after\n        # we've made sure the user didn't ask for an absolute tolerance only,\n        # because we don't want to raise errors about the relative tolerance if\n        # we aren't even going to use it.\n        rel = self.rel if self.rel is not None else self.DEFAULT_RELATIVE_TOLERANCE\n        # expected is SupportAbs, checked in __init__.\n        # The typing here is not exact...\n        abs_expected: ExpectedT = abs(self.expected)  # type: ignore[arg-type]\n        relative_tolerance: float | Decimal = rel * abs_expected  # type: ignore[operator]\n","sourceCodeStart":547,"sourceCodeEnd":583,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/approx.py#L547-L583","documentation":"Raised by ApproxScalar.tolerance when the absolute tolerance passed to pytest.approx() is NaN. pytest forbids NaN tolerances because no real value could ever satisfy a NaN-based comparison, making the assertion meaningless.","triggerScenarios":"Call pytest.approx(x, abs=float('nan')) or pass any expression that evaluates to NaN for the abs parameter, then perform a comparison (e.g. assert v == approx(1.0, abs=math.nan)).","commonSituations":"Tolerance values computed from data (e.g. abs=std_dev) where the source array contains NaNs; copy-pasting a constant incorrectly; downstream of a division that produced NaN.","solutions":["Replace the NaN abs tolerance with an explicit finite number, e.g. abs=1e-6.","If the tolerance is derived, guard/sanitize the source data so it cannot be NaN before passing it to approx().","Run with -s / a debugger to print the value of abs right before the approx() call to find where the NaN originates."],"exampleFix":"// before\nassert v == approx(1.0, abs=float('nan'))\n// after\nassert v == approx(1.0, abs=1e-6)","handlingStrategy":"validation","validationCode":"import math\n\ndef safe_approx_abs(x, abs_tol):\n    if abs_tol is None or math.isnan(abs_tol):\n        raise ValueError(f'abs tolerance must be a finite number, got {abs_tol!r}')\n    return pytest.approx(x, abs=abs_tol)","typeGuard":"import math\n\ndef is_finite_number(v) -> bool:\n    return isinstance(v, (int, float)) and not math.isnan(v) and not math.isinf(v)","tryCatchPattern":"try:\n    assert v == pytest.approx(1.0, abs=tol)\nexcept ValueError as e:\n    if 'absolute tolerance' in str(e):\n        # fall back to a safe default tolerance\n        assert v == pytest.approx(1.0, abs=1e-6)\n    else:\n        raise","preventionTips":["Never derive abs/rel tolerances from unsanitized data that may contain NaN.","Validate tolerances once at the boundary (config load, fixture setup) rather than at every call.","Prefer explicit small constants (1e-6, 1e-9) over computed tolerances when possible."],"tags":["pytest","approx","validation","nan"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}