{"record":{"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/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/approx.py#L547-L583","documentation":"The ApproxScalar.tolerance property rejects a NaN absolute tolerance because comparisons against NaN always evaluate to False, which would make every assertion silently fail in a confusing way. pytest raises ValueError so the user sees the bad input immediately. The check uses math.isnan and runs after the negativity check.","triggerScenarios":"Calling approx(1.0, abs=float('nan')); abs loaded from a JSON/CSV field that contained 'nan' or non-numeric data parsed to NaN; arithmetic that produces NaN (0.0/0.0). Triggered at ApproxScalar.tolerance (src/_pytest/approx.py:564-565).","commonSituations":"Parsing tolerances from data files where missing values become NaN; tolerance computed as a ratio whose denominator is zero; cross-platform float parsing differences.","solutions":["Pass a finite positive tolerance: `approx(1.0, abs=1e-3)`.","Sanitize loaded tolerances: `if math.isnan(t): raise ValueError(...)` or `t = t if not math.isnan(t) else DEFAULT`.","Fix upstream computation so the denominator cannot be zero."],"exampleFix":"# before\napprox(value, abs=float('nan'))\n# after\napprox(value, abs=1e-3)","handlingStrategy":"validation","validationCode":"import math\ndef is_finite_tolerance(t) -> bool:\n    return t is None or (isinstance(t, (int, float)) and not math.isnan(t))\n# usage\nif not is_finite_tolerance(abs_tol):\n    raise ValueError(f'absolute tolerance must be finite, got {abs_tol}')\nassert actual == approx(expected, abs=abs_tol)","typeGuard":"import math\ndef is_finite_scalar(v) -> bool:\n    return isinstance(v, (int, float)) and not math.isnan(v)","tryCatchPattern":null,"preventionTips":["Reject NaN tolerances at config load.","Guard divisions whose denominator could be zero before computing tolerance.","Unit-test tolerance generation paths with edge inputs."],"tags":["pytest","approx","tolerance","nan","value-validation"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}