pytest-dev/pytest · error · TypeError
relative tolerance for a scalar value must be an int, float…
Error message
relative tolerance for a scalar value must be an int, float or Decimal, got {type(rel).__name__} What it means
ApproxScalar.__init__ validates that when a relative tolerance (rel) is supplied, it must be an int, float, or Decimal. Any other type (string, timedelta, None-as-sentinel misuse, custom object) is rejected with the offending type name. This is enforced because relative tolerance is multiplied by abs(expected); non-numeric types would produce a TypeError later in a confusing place, so pytest fails fast.
Solutions
- Pass rel as a plain float: `approx(1.0, rel=0.01)`.
- If the tolerance comes from config/env, cast explicitly: `rel=float(cfg['rel'])`.
- For Decimal comparisons, pass a Decimal rel: `approx(Decimal('1'), rel=Decimal('0.01'))`.
Example fix
# before approx(1.0, rel='0.01') # after approx(1.0, rel=0.01)
Defensive patterns
Strategy: validation
Validate before calling
from decimal import Decimal
def is_valid_rel(rel) -> bool:
return rel is None or isinstance(rel, (int, float, Decimal))
# usage
rel = float(config['rel']) if isinstance(config['rel'], str) else config['rel']
assert is_valid_rel(rel)
assert actual == approx(expected, rel=rel) Type guard
from decimal import Decimal
def is_scalar_rel(v) -> bool:
return v is None or isinstance(v, (int, float, Decimal)) Prevention
- Always pass rel as a literal float or Decimal.
- Cast config/env tolerances with float(...) before passing.
- Do not pass timedelta as rel for scalar comparisons.
When it happens
Trigger: Passing rel='0.1', rel=timedelta(seconds=1) to a scalar approx, rel=np.float64(...) (this one is accepted), or rel=[0.1]. Triggered at ApproxScalar.__init__ (src/_pytest/approx.py:448-453). Note: bool is a subclass of int, so rel=True/False passes but yields nonsensical results.
Common situations: Copy-pasting tolerance syntax from datetime examples into scalar comparisons; reading tolerances from config files as strings; mixing up rel and abs argument order.
Related errors
- absolute tolerance for a scalar value must be an int, float…
- absolute tolerance can't be negative
- expected value must support abs(...) when relative…
- absolute tolerance can't be NaN.
- pytest.approx() does not support relative tolerance for…
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/7daa572e18071a41.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/approx.py:450
# Using Real should be better than this Union, but not possible yet:
# https://github.com/python/typeshed/pull/3108
DEFAULT_ABSOLUTE_TOLERANCE: float | Decimal = 1e-12
DEFAULT_RELATIVE_TOLERANCE: float | Decimal = 1e-6
rel: float | Decimal | None
abs: float | Decimal | None
def __init__(
self,
expected: ExpectedT,
rel: float | Decimal | timedelta | None,
abs: float | Decimal | timedelta | None,
nan_ok: bool,
) -> None:
__tracebackhide__ = True
if rel is not None:
if not isinstance(rel, (int, float, Decimal)):
raise TypeError(
f"relative tolerance for a scalar value must be an int, float or Decimal, "
f"got {type(rel).__name__}"
)
if not isinstance(expected, SupportsAbs):
raise TypeError(
f"expected value must support abs(...) when relative tolerance is used, "
f"got {type(expected).__name__}"
)
if abs is not None and not isinstance(abs, (int, float, Decimal)):
raise TypeError(
f"absolute tolerance for a scalar value must be an int, float or Decimal, "
f"got {type(abs).__name__}"
)
super().__init__(expected, rel=rel, abs=abs, nan_ok=nan_ok)
def __repr__(self) -> str:
"""Return a string communicating both the expected value and the
tolerance for the comparison being made.View on GitHub (pinned to 0d6fbdeffa)