pytest-dev/pytest · error · ValueError
absolute tolerance can't be negative
Error message
absolute tolerance can't be negative: {absolute_tolerance} What it means
The ApproxScalar.tolerance property computes the effective absolute tolerance and rejects negative values because a negative tolerance window makes no geometric sense (no value would ever be 'within' a negative distance of expected). pytest raises ValueError naming the offending value so the user can correct it. This is checked before the NaN check.
Solutions
- Use a positive absolute tolerance: `approx(1.0, abs=1e-3)`.
- If computing tolerance dynamically, clamp with `abs(abs_tol, ...)` or `max(abs_tol, 0.0)` after fixing the sign logic.
- Validate config-supplied tolerances at load time and fail with a clearer message.
Example fix
# before approx(value, abs=-1e-3) # after approx(value, abs=1e-3)
Defensive patterns
Strategy: validation
Validate before calling
def is_nonneg_tolerance(t) -> bool:
return t is None or (isinstance(t, (int, float)) and t >= 0)
# usage
if not is_nonneg_tolerance(abs_tol):
raise ValueError(f'absolute tolerance must be >= 0, got {abs_tol}')
assert actual == approx(expected, abs=abs_tol) Type guard
from decimal import Decimal
def is_nonneg_scalar(v) -> bool:
return isinstance(v, (int, float, Decimal)) and v >= 0 Prevention
- Validate abs >= 0 before passing to approx.
- Audit sign-producing arithmetic that feeds abs.
- Add a config-loader check that rejects negative tolerances.
When it happens
Trigger: Calling approx(1.0, abs=-1e-3); passing abs=float('-1e-3'); abs computed/loaded as negative due to a sign error or subtraction bug. Triggered at ApproxScalar.tolerance (src/_pytest/approx.py:560-563).
Common situations: Tolerance read from config where a stray minus sign was introduced; arithmetic on tolerances (abs=a-b) that can go negative; copy-paste errors.
Related errors
- absolute tolerance can't be NaN.
- absolute tolerance for a scalar value must be an int, float…
- relative tolerance can't be negative
- relative 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/405375e8bb014fbd.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/approx.py:561
return result
__hash__ = None
@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__.View on GitHub (pinned to 0d6fbdeffa)