pytest-dev/pytest · error · ValueError

absolute tolerance can't be negative: {abs}

Error message

absolute tolerance can't be negative: {abs}

What it means

ApproxTimedelta.__init__ rejects a negative timedelta absolute tolerance. A negative tolerance makes the comparison meaningless (no value would be within a negative distance of the expected).

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 98b357f69e)

Solutions

  1. Use abs(timedelta(...)) or ensure the value is non-negative: abs=timedelta(seconds=1).
  2. Sanitize the source so negative durations are clamped to zero or corrected.
  3. Add an assertion in the fixture producing the tolerance.

Example fix

// before
assert got == approx(dt, abs=timedelta(seconds=-1))
// after
assert got == approx(dt, abs=timedelta(seconds=1))
Defensive patterns

Strategy: validation

Validate before calling

from datetime import timedelta

def approx_dt(value, abs_tol):
    if isinstance(abs_tol, timedelta) and abs_tol < timedelta(0):
        abs_tol = -abs_tol
    return pytest.approx(value, abs=abs_tol)

Type guard

from datetime import timedelta

def is_nonneg_timedelta(v) -> bool:
    return isinstance(v, timedelta) and v >= timedelta(0)

Prevention

When it happens

Trigger: Call pytest.approx(dt, abs=timedelta(seconds=-1)) or any call where the abs timedelta is less than timedelta(0).

Common situations: Tolerance computed from a subtraction that can go negative; sign error when constructing the timedelta; parametrized fixture that inadvertently yields negative durations.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/be9be101889764ff.json. Report an issue: GitHub.