pytest-dev/pytest · error · TypeError
relative tolerance for timedelta must be a number, got {type
Error message
relative tolerance for timedelta must be a number, got {type(rel).__name__} What it means
ApproxTimedelta.__init__ requires the relative tolerance for a timedelta comparison to be a number (int or float), because rel is multiplied by abs(expected) (a timedelta) to produce a timedelta tolerance. Non-numeric rel values cannot be multiplied.
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 98b357f69e)
Solutions
- Pass rel as a float: approx(td, rel=0.01).
- If you have a string tolerance, cast it: rel=float(my_str).
- Use abs=timedelta(...) instead if you actually have a duration tolerance.
Example fix
// before assert got == approx(td, rel='0.01') // after assert got == approx(td, rel=0.01)
Defensive patterns
Strategy: type-guard
Validate before calling
def approx_td_rel(value, rel):
if not isinstance(rel, (int, float)):
raise TypeError(f'rel must be a number, got {type(rel).__name__}')
return pytest.approx(value, rel=rel) Type guard
def is_number(v) -> bool:
return isinstance(v, (int, float)) and not isinstance(v, bool) Prevention
- Cast string tolerances with float() at the config boundary.
- Keep abs=timedelta and rel=float distinct in your helpers; do not let callers swap them.
When it happens
Trigger: Call pytest.approx(some_timedelta, rel='0.01') or rel=timedelta(...) — any non-int/float value for rel when expected is a timedelta.
Common situations: Reading rel from a config file as a string; accidentally passing a timedelta as rel instead of abs; copy-paste errors.
Related errors
- absolute tolerance for datetime/timedelta must be a timedelt
- relative tolerance can't be negative: {rel}
- relative tolerance can't be infinite.
- pytest.approx() only supports ordered sequences, but got: {e
- absolute tolerance can't be NaN.
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/a44456c59550bba0.json.
Report an issue: GitHub.