pytest-dev/pytest · error · TypeError

absolute tolerance for datetime/timedelta must be a timedelt

Error message

absolute tolerance for datetime/timedelta must be a timedelta, got {type(abs).__name__}

What it means

ApproxTimedelta.__init__ requires the absolute tolerance for datetime/timedelta comparisons to itself be a timedelta, since the units must match the values being compared. Passing a raw number is ambiguous (seconds? microseconds?) and is rejected.

Source

Thrown at src/_pytest/approx.py:664

        if isinstance(expected, datetime) and rel is not None:
            raise TypeError(
                "pytest.approx() does not support relative tolerance for "
                "datetime comparisons. Use abs=timedelta(...) instead."
            )
        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

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Wrap the tolerance in timedelta with explicit units: abs=timedelta(seconds=1).
  2. If you have a numeric tolerance in seconds, write abs=timedelta(seconds=n).
  3. Double-check the units (seconds vs milliseconds vs microseconds) to avoid off-by-1000 bugs.

Example fix

// before
assert got == approx(dt, abs=1.0)
// after
from datetime import timedelta
assert got == approx(dt, abs=timedelta(seconds=1))
Defensive patterns

Strategy: type-guard

Validate before calling

from datetime import timedelta

def approx_dt(value, abs_tol):
    if not isinstance(abs_tol, timedelta):
        raise TypeError(f'abs must be a timedelta, got {type(abs_tol).__name__}')
    return pytest.approx(value, abs=abs_tol)

Type guard

from datetime import timedelta

def is_timedelta(v) -> bool:
    return isinstance(v, timedelta)

Prevention

When it happens

Trigger: Call pytest.approx(dt, abs=1.0) or approx(dt, abs=2) — any non-timedelta value for abs when expected is a datetime/timedelta.

Common situations: Migrating a numeric approx(x, abs=0.001) call to datetime without wrapping the tolerance in timedelta(...); copy-pasting tolerance kwargs.

Related errors


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