{"record":{"id":"e10b63e3e0116544","repo":"pytest-dev/pytest","slug":"relative-tolerance-can-t-be-nan","errorCode":null,"errorMessage":"relative tolerance can't be NaN.","messagePattern":"relative tolerance can't be NaN\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/approx.py","lineNumber":589,"sourceCode":"                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\n        if relative_tolerance < 0:\n            raise ValueError(\n                f\"relative tolerance can't be negative: {relative_tolerance}\"\n            )\n        if math.isnan(relative_tolerance):\n            raise ValueError(\"relative tolerance can't be NaN.\")\n\n        # Return the larger of the relative and absolute tolerances.\n        return max(relative_tolerance, absolute_tolerance)\n\n\nclass ApproxDecimal(ApproxScalar[Decimal]):\n    \"\"\"Perform approximate comparisons where the expected value is a Decimal.\"\"\"\n\n    DEFAULT_ABSOLUTE_TOLERANCE = Decimal(\"1e-12\")\n    DEFAULT_RELATIVE_TOLERANCE = Decimal(\"1e-6\")\n    rel: Decimal | None\n    abs: Decimal | None\n\n    def __init__(\n        self,\n        expected: Decimal,\n        rel: float | Decimal | timedelta | None,\n        abs: float | Decimal | timedelta | None,","sourceCodeStart":571,"sourceCodeEnd":607,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/approx.py#L571-L607","documentation":"In ApproxScalar.tolerance, if the computed relative tolerance (rel * abs(expected)) is NaN, pytest raises ValueError. This happens when rel is NaN or when expected is NaN (since abs(NaN) is NaN, and rel*NaN is NaN). Comparisons against NaN always fail, so pytest surfaces the bad input explicitly instead of producing silently-failing assertions.","triggerScenarios":"Calling approx(float('nan'), rel=0.1) (expected is NaN), approx(1.0, rel=float('nan')), or approx(value, rel=nan_from_config). Triggered at ApproxScalar.tolerance (src/_pytest/approx.py:588-589).","commonSituations":"Comparing NaN expected values with a relative tolerance (use nan_ok=True for NaN-equality instead); tolerance parsed from data with missing/non-numeric fields; upstream computation producing NaN.","solutions":["To treat NaN as equal to NaN, use `approx(value, nan_ok=True)` and avoid rel on NaN expected.","Sanitize the expected value: `assert not math.isnan(v)` before constructing approx.","Fix the upstream NaN source (zero-denominator division, missing data)."],"exampleFix":"# before\napprox(float('nan'), rel=0.01)\n# after\napprox(float('nan'), nan_ok=True)","handlingStrategy":"validation","validationCode":"import math\ndef is_safe_for_rel(expected, rel) -> bool:\n    if rel is None:\n        return True\n    if isinstance(expected, (int, float)) and math.isnan(expected):\n        return False\n    return isinstance(rel, (int, float)) and not math.isnan(rel)\n# usage\nif not is_safe_for_rel(expected, rel):\n    # use nan_ok instead of rel for NaN expected\n    assert actual == approx(expected, nan_ok=True)\nelse:\n    assert actual == approx(expected, rel=rel)","typeGuard":"import math\ndef is_finite_rel_source(expected, rel) -> bool:\n    return (\n        isinstance(rel, (int, float)) and not math.isnan(rel)\n        and not (isinstance(expected, float) and math.isnan(expected))\n    )","tryCatchPattern":null,"preventionTips":["Use nan_ok=True instead of rel when the expected value may be NaN.","Sanitize expected values: assert not math.isnan(v).","Fix upstream computations that produce NaN."],"tags":["pytest","approx","tolerance","nan","relative"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}