pytest-dev/pytest · error · ValueError
relative tolerance can't be NaN.
Error message
relative tolerance can't be NaN.
What it means
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.
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).
Example fix
# before
approx(float('nan'), rel=0.01)
# after
approx(float('nan'), nan_ok=True) Defensive patterns
Strategy: validation
Validate before calling
import math
def is_safe_for_rel(expected, rel) -> bool:
if rel is None:
return True
if isinstance(expected, (int, float)) and math.isnan(expected):
return False
return isinstance(rel, (int, float)) and not math.isnan(rel)
# usage
if not is_safe_for_rel(expected, rel):
# use nan_ok instead of rel for NaN expected
assert actual == approx(expected, nan_ok=True)
else:
assert actual == approx(expected, rel=rel) Type guard
import math
def is_finite_rel_source(expected, rel) -> bool:
return (
isinstance(rel, (int, float)) and not math.isnan(rel)
and not (isinstance(expected, float) and math.isnan(expected))
) Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- absolute tolerance can't be NaN.
- pytest.approx() does not support relative tolerance for…
- relative tolerance can't be negative
- absolute tolerance can't be negative
- absolute tolerance for a scalar value must be an int, float…
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/e10b63e3e0116544.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/approx.py:589
return absolute_tolerance
# Figure out what the relative tolerance should be. ``self.rel`` is
# either None or a value specified by the user. This is done after
# we've made sure the user didn't ask for an absolute tolerance only,
# because we don't want to raise errors about the relative tolerance if
# we aren't even going to use it.
rel = self.rel if self.rel is not None else self.DEFAULT_RELATIVE_TOLERANCE
# expected is SupportAbs, checked in __init__.
# The typing here is not exact...
abs_expected: ExpectedT = abs(self.expected) # type: ignore[arg-type]
relative_tolerance: float | Decimal = rel * abs_expected # type: ignore[operator]
if relative_tolerance < 0:
raise ValueError(
f"relative tolerance can't be negative: {relative_tolerance}"
)
if math.isnan(relative_tolerance):
raise ValueError("relative tolerance can't be NaN.")
# Return the larger of the relative and absolute tolerances.
return max(relative_tolerance, absolute_tolerance)
class ApproxDecimal(ApproxScalar[Decimal]):
"""Perform approximate comparisons where the expected value is a Decimal."""
DEFAULT_ABSOLUTE_TOLERANCE = Decimal("1e-12")
DEFAULT_RELATIVE_TOLERANCE = Decimal("1e-6")
rel: Decimal | None
abs: Decimal | None
def __init__(
self,
expected: Decimal,
rel: float | Decimal | timedelta | None,
abs: float | Decimal | timedelta | None,View on GitHub (pinned to 0d6fbdeffa)