{"id":"be9be101889764ff","repo":"pytest-dev/pytest","slug":"absolute-tolerance-can-t-be-negative-abs","errorCode":null,"errorMessage":"absolute tolerance can't be negative: {abs}","messagePattern":"absolute tolerance can't be negative: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/approx.py","lineNumber":669,"sourceCode":"        if nan_ok:\n            raise TypeError(\n                \"pytest.approx() does not support nan_ok for \"\n                \"datetime/timedelta comparisons.\"\n            )\n        if abs is None and rel is None:\n            raise TypeError(\n                \"pytest.approx() requires an explicit tolerance for \"\n                \"datetime/timedelta comparisons: \"\n                \"e.g. approx(expected, abs=timedelta(seconds=1)) \"\n                \"or approx(expected, rel=0.01)\"\n            )\n        if abs is not None and not isinstance(abs, timedelta):\n            raise TypeError(\n                f\"absolute tolerance for datetime/timedelta must be a \"\n                f\"timedelta, got {type(abs).__name__}\"\n            )\n        if abs is not None and abs < timedelta(0):\n            raise ValueError(f\"absolute tolerance can't be negative: {abs}\")\n        if rel is not None:\n            if not isinstance(rel, (int, float)):\n                raise TypeError(\n                    f\"relative tolerance for timedelta must be a \"\n                    f\"number, got {type(rel).__name__}\"\n                )\n            if rel < 0:\n                raise ValueError(f\"relative tolerance can't be negative: {rel}\")\n            if math.isnan(rel):\n                raise ValueError(\"relative tolerance can't be NaN.\")\n            if math.isinf(rel):\n                raise ValueError(\"relative tolerance can't be infinite.\")\n        # Compute the effective tolerance. abs_tolerance is a timedelta, rel * expected\n        # gives a timedelta (timedelta * float works in Python).\n        abs_tolerance = abs\n        if rel is None:\n            rel_tolerance = None\n        else:","sourceCodeStart":651,"sourceCodeEnd":687,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/approx.py#L651-L687","documentation":"ApproxTimedelta.__init__ rejects a negative timedelta absolute tolerance. A negative tolerance makes the comparison meaningless (no value would be within a negative distance of the expected).","triggerScenarios":"Call pytest.approx(dt, abs=timedelta(seconds=-1)) or any call where the abs timedelta is less than timedelta(0).","commonSituations":"Tolerance computed from a subtraction that can go negative; sign error when constructing the timedelta; parametrized fixture that inadvertently yields negative durations.","solutions":["Use abs(timedelta(...)) or ensure the value is non-negative: abs=timedelta(seconds=1).","Sanitize the source so negative durations are clamped to zero or corrected.","Add an assertion in the fixture producing the tolerance."],"exampleFix":"// before\nassert got == approx(dt, abs=timedelta(seconds=-1))\n// after\nassert got == approx(dt, abs=timedelta(seconds=1))","handlingStrategy":"validation","validationCode":"from datetime import timedelta\n\ndef approx_dt(value, abs_tol):\n    if isinstance(abs_tol, timedelta) and abs_tol < timedelta(0):\n        abs_tol = -abs_tol\n    return pytest.approx(value, abs=abs_tol)","typeGuard":"from datetime import timedelta\n\ndef is_nonneg_timedelta(v) -> bool:\n    return isinstance(v, timedelta) and v >= timedelta(0)","tryCatchPattern":null,"preventionTips":["Use abs(timedelta(...)) when tolerances are derived from subtractions.","Validate fixture-produced durations are non-negative."],"tags":["pytest","approx","datetime","validation"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}