pytest-dev/pytest · error · ValueError
absolute tolerance can't be NaN.
Error message
absolute tolerance can't be NaN.
What it means
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.
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.
Example fix
# before
approx(value, abs=float('nan'))
# after
approx(value, abs=1e-3) Defensive patterns
Strategy: validation
Validate before calling
import math
def is_finite_tolerance(t) -> bool:
return t is None or (isinstance(t, (int, float)) and not math.isnan(t))
# usage
if not is_finite_tolerance(abs_tol):
raise ValueError(f'absolute tolerance must be finite, got {abs_tol}')
assert actual == approx(expected, abs=abs_tol) Type guard
import math
def is_finite_scalar(v) -> bool:
return isinstance(v, (int, float)) and not math.isnan(v) Prevention
- Reject NaN tolerances at config load.
- Guard divisions whose denominator could be zero before computing tolerance.
- Unit-test tolerance generation paths with edge inputs.
When it happens
Trigger: 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).
Common situations: Parsing tolerances from data files where missing values become NaN; tolerance computed as a ratio whose denominator is zero; cross-platform float parsing differences.
Related errors
- absolute tolerance can't be negative
- relative tolerance can't be NaN.
- relative tolerance can't be negative
- absolute tolerance for a scalar value must be an int, float…
- expected value must support abs(...) when relative…
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/8d873abd7dd39eb0.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/approx.py:565
@property
def tolerance(self):
"""Return the tolerance for the comparison.
This could be either an absolute tolerance or a relative tolerance,
depending on what the user specified or which would be larger.
"""
# Figure out what the absolute tolerance should be. ``self.abs`` is
# either None or a value specified by the user.
absolute_tolerance = (
self.abs if self.abs is not None else self.DEFAULT_ABSOLUTE_TOLERANCE
)
if absolute_tolerance < 0:
raise ValueError(
f"absolute tolerance can't be negative: {absolute_tolerance}"
)
if math.isnan(absolute_tolerance):
raise ValueError("absolute tolerance can't be NaN.")
# If the user specified an absolute tolerance but not a relative one,
# just return the absolute tolerance.
if self.rel is None:
if self.abs is not None:
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]
View on GitHub (pinned to 0d6fbdeffa)