pytest-dev/pytest · error · ValueError
absolute tolerance can't be negative
Error message
absolute tolerance can't be negative: {abs} What it means
Raised by ApproxTimedelta.__init__ when abs is a timedelta but negative. A negative tolerance is meaningless (it would accept nothing or invert the comparison) and almost always indicates a sign mistake. The check runs after confirming abs is a timedelta, so the value can be safely compared to timedelta(0).
Solutions
- Ensure the tolerance is non-negative: use builtins.abs(...) on the computation.
- Pass an explicit positive timedelta literal.
- Review how the tolerance value is derived before passing it to approx().
Example fix
// before approx(td, abs=expected - actual) # may be negative // after approx(td, abs=abs(expected - actual))
Defensive patterns
Strategy: validation
Validate before calling
from datetime import timedelta
def nonneg_td(v):
if v is not None and v < timedelta(0):
raise ValueError('tolerance must be non-negative')
return v Type guard
from datetime import timedelta
def is_nonneg_timedelta(v) -> bool:
return v is None or (isinstance(v, timedelta) and v >= timedelta(0)) Prevention
- Wrap computed tolerances in builtins.abs().
- Validate tolerance sign at fixture construction.
When it happens
Trigger: approx(td, abs=timedelta(seconds=-1)); computing abs from a subtraction that can go negative without builtins.abs().
Common situations: Tolerance computed as (expected - actual) without wrapping in abs(); off-by-sign bugs in test fixture generation.
Related errors
- relative tolerance can't be negative
- relative tolerance can't be infinite.
- absolute tolerance for datetime/timedelta must be a…
- relative tolerance for timedelta must be a number, got
- absolute tolerance can't be NaN.
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/be9be101889764ff.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/approx.py:669
if nan_ok:
raise TypeError(
"pytest.approx() does not support nan_ok for "
"datetime/timedelta comparisons."
)
if abs is None and rel is None:
raise TypeError(
"pytest.approx() requires an explicit tolerance for "
"datetime/timedelta comparisons: "
"e.g. approx(expected, abs=timedelta(seconds=1)) "
"or approx(expected, rel=0.01)"
)
if abs is not None and not isinstance(abs, timedelta):
raise TypeError(
f"absolute tolerance for datetime/timedelta must be a "
f"timedelta, got {type(abs).__name__}"
)
if abs is not None and abs < timedelta(0):
raise ValueError(f"absolute tolerance can't be negative: {abs}")
if rel is not None:
if not isinstance(rel, (int, float)):
raise TypeError(
f"relative tolerance for timedelta must be a "
f"number, got {type(rel).__name__}"
)
if rel < 0:
raise ValueError(f"relative tolerance can't be negative: {rel}")
if math.isnan(rel):
raise ValueError("relative tolerance can't be NaN.")
if math.isinf(rel):
raise ValueError("relative tolerance can't be infinite.")
# Compute the effective tolerance. abs_tolerance is a timedelta, rel * expected
# gives a timedelta (timedelta * float works in Python).
abs_tolerance = abs
if rel is None:
rel_tolerance = None
else:View on GitHub (pinned to 0d6fbdeffa)