pytest-dev/pytest · error · ValueError
absolute tolerance can't be NaN.
Error message
absolute tolerance can't be NaN.
What it means
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.
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 98b357f69e)
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.
Example fix
// before
assert v == approx(1.0, abs=float('nan'))
// after
assert v == approx(1.0, abs=1e-6) Defensive patterns
Strategy: validation
Validate before calling
import math
def safe_approx_abs(x, abs_tol):
if abs_tol is None or math.isnan(abs_tol):
raise ValueError(f'abs tolerance must be a finite number, got {abs_tol!r}')
return pytest.approx(x, abs=abs_tol) Type guard
import math
def is_finite_number(v) -> bool:
return isinstance(v, (int, float)) and not math.isnan(v) and not math.isinf(v) Try / catch
try:
assert v == pytest.approx(1.0, abs=tol)
except ValueError as e:
if 'absolute tolerance' in str(e):
# fall back to a safe default tolerance
assert v == pytest.approx(1.0, abs=1e-6)
else:
raise Prevention
- 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.
When it happens
Trigger: 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)).
Common situations: 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.
Related errors
- relative tolerance can't be NaN.
- relative tolerance can't be negative: {relative_tolerance}
- absolute tolerance can't be negative: {abs}
- relative tolerance can't be negative: {rel}
- relative tolerance can't be infinite.
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/8d873abd7dd39eb0.json.
Report an issue: GitHub.