pytest-dev/pytest · error · TypeError

relative tolerance for timedelta must be a number, got

Error message

relative tolerance for timedelta must be a number, got {type(rel).__name__}

What it means

Raised by ApproxTimedelta.__init__ when rel is provided for a timedelta comparison but is not an int or float. Relative tolerance for timedelta is a dimensionless multiplier (e.g. 0.01 = 1%), so non-numeric values are rejected with TypeError naming the offending type.

Solutions

  1. Use abs=timedelta(...) for absolute time tolerance.
  2. Ensure rel is a numeric literal: rel=0.01.
  3. Convert config strings with float() before passing.

Example fix

// before
approx(td, rel=timedelta(seconds=1))
// after
approx(td, abs=timedelta(seconds=1))
Defensive patterns

Strategy: type-guard

Validate before calling

def approx_td_rel(expected, *, rel=None, **kw):
    if rel is not None and not isinstance(rel, (int, float)):
        raise TypeError('rel must be a number')
    return approx(expected, rel=rel, **kw)

Type guard

import numbers
def is_number_or_none(v) -> bool:
    return v is None or isinstance(v, numbers.Real)

Prevention

When it happens

Trigger: approx(td, rel=timedelta(seconds=1)); approx(td, rel='0.01'); approx(td, rel=None_str).

Common situations: Confusing abs (timedelta) and rel (number) parameter types; passing a string from config into rel.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/a44456c59550bba0. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/approx.py:672

                "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:
            # Checked above.
            assert not isinstance(expected, datetime)
            rel_tolerance = rel * builtins.abs(expected)

View on GitHub (pinned to 0d6fbdeffa)