{"record":{"id":"7daa572e18071a41","repo":"pytest-dev/pytest","slug":"relative-tolerance-for-a-scalar-value-must-be-an-i","errorCode":null,"errorMessage":"relative tolerance for a scalar value must be an int, float or Decimal, got {type(rel).__name__}","messagePattern":"relative tolerance for a scalar value must be an int, float or Decimal, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/approx.py","lineNumber":450,"sourceCode":"\n    # Using Real should be better than this Union, but not possible yet:\n    # https://github.com/python/typeshed/pull/3108\n    DEFAULT_ABSOLUTE_TOLERANCE: float | Decimal = 1e-12\n    DEFAULT_RELATIVE_TOLERANCE: float | Decimal = 1e-6\n    rel: float | Decimal | None\n    abs: float | Decimal | None\n\n    def __init__(\n        self,\n        expected: ExpectedT,\n        rel: float | Decimal | timedelta | None,\n        abs: float | Decimal | timedelta | None,\n        nan_ok: bool,\n    ) -> None:\n        __tracebackhide__ = True\n        if rel is not None:\n            if not isinstance(rel, (int, float, Decimal)):\n                raise TypeError(\n                    f\"relative tolerance for a scalar value must be an int, float or Decimal, \"\n                    f\"got {type(rel).__name__}\"\n                )\n            if not isinstance(expected, SupportsAbs):\n                raise TypeError(\n                    f\"expected value must support abs(...) when relative tolerance is used, \"\n                    f\"got {type(expected).__name__}\"\n                )\n        if abs is not None and not isinstance(abs, (int, float, Decimal)):\n            raise TypeError(\n                f\"absolute tolerance for a scalar value must be an int, float or Decimal, \"\n                f\"got {type(abs).__name__}\"\n            )\n        super().__init__(expected, rel=rel, abs=abs, nan_ok=nan_ok)\n\n    def __repr__(self) -> str:\n        \"\"\"Return a string communicating both the expected value and the\n        tolerance for the comparison being made.","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/approx.py#L432-L468","documentation":"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.","triggerScenarios":"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.","commonSituations":"Copy-pasting tolerance syntax from datetime examples into scalar comparisons; reading tolerances from config files as strings; mixing up rel and abs argument order.","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'))`."],"exampleFix":"# before\napprox(1.0, rel='0.01')\n# after\napprox(1.0, rel=0.01)","handlingStrategy":"validation","validationCode":"from decimal import Decimal\ndef is_valid_rel(rel) -> bool:\n    return rel is None or isinstance(rel, (int, float, Decimal))\n# usage\nrel = float(config['rel']) if isinstance(config['rel'], str) else config['rel']\nassert is_valid_rel(rel)\nassert actual == approx(expected, rel=rel)","typeGuard":"from decimal import Decimal\ndef is_scalar_rel(v) -> bool:\n    return v is None or isinstance(v, (int, float, Decimal))","tryCatchPattern":null,"preventionTips":["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."],"tags":["pytest","approx","tolerance","type-validation","scalar"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}