{"id":"98f4c88266d36623","repo":"pytest-dev/pytest","slug":"tmp-path-retention-count-must-be-0-current-inp","errorCode":null,"errorMessage":"tmp_path_retention_count must be >= 0. Current input: {count}.","messagePattern":"tmp_path_retention_count must be >= 0\\. Current input: (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/tmpdir.py","lineNumber":97,"sourceCode":"        # Register cleanups for session finish. Also called atexit as a last\n        # resort if sessionfinish for some reason doesn't happen.\n        self._exit_stack = ExitStack()\n\n    @classmethod\n    def from_config(\n        cls,\n        config: Config,\n        *,\n        _ispytest: bool = False,\n    ) -> TempPathFactory:\n        \"\"\"Create a factory according to pytest configuration.\n\n        :meta private:\n        \"\"\"\n        check_ispytest(_ispytest)\n        count = int(config.getini(\"tmp_path_retention_count\"))\n        if count < 0:\n            raise ValueError(\n                f\"tmp_path_retention_count must be >= 0. Current input: {count}.\"\n            )\n\n        policy: RetentionType = config.getini(\"tmp_path_retention_policy\")\n\n        return cls(\n            given_basetemp=config.option.basetemp,\n            trace=config.trace.get(\"tmpdir\"),\n            retention_count=count,\n            retention_policy=policy,\n            _ispytest=True,\n        )\n\n    def _ensure_relative_to_basetemp(self, basename: str) -> str:\n        basename = os.path.normpath(basename)\n        if (self.getbasetemp() / basename).resolve().parent != self.getbasetemp():\n            raise ValueError(f\"{basename} is not a normalized and relative path\")\n        return basename","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/tmpdir.py#L79-L115","documentation":"Raised by TempPathFactory.from_config during pytest_configure if the ini option tmp_path_retention_count parses to a negative integer. The option controls how many recent tmp_path session directories pytest keeps around; a negative value is meaningless and is rejected eagerly so later cleanup logic (which indexes by count) does not break.","triggerScenarios":"Setting tmp_path_retention_count = -1 (or any negative) in pytest.ini, pyproject.toml [tool.pytest.ini_options], tox.ini, or setup.cfg, then starting pytest. The check runs at configure time, so the failure happens before any test executes.","commonSituations":"Confusing retention_count with retention_policy (setting -1 meaning 'none'); copy-pasted config from a blog post; intending 'never delete' and using a negative number instead of a large positive one.","solutions":["Set tmp_path_retention_count to 0 or a positive integer (default is 3).","If the intent is 'do not keep anything', use tmp_path_retention_policy = none instead of a negative count.","Search all ini sources (pytest.ini, pyproject.toml, tox.ini, setup.cfg, CLI --override-ini) for tmp_path_retention_count."],"exampleFix":"// before (pytest.ini)\n[pytest]\ntmp_path_retention_count = -1\n\n// after\n[pytest]\ntmp_path_retention_count = 0\ntmp_path_retention_policy = none","handlingStrategy":"validation","validationCode":"def validate_retention_count(config_value):\n    n = int(config_value)\n    if n < 0:\n        raise ValueError(f\"tmp_path_retention_count must be >= 0, got {n}\")\n    return n","typeGuard":"def is_valid_retention_count(v) -> bool:\n    try:\n        return int(v) >= 0\n    except (TypeError, ValueError):\n        return False","tryCatchPattern":null,"preventionTips":["Keep tmp_path_retention_count at the default (3) unless you have a reason.","Use tmp_path_retention_policy = none to disable retention rather than a negative count.","Validate ini overrides in a pre-commit hook or a small conftest sanity check."],"tags":["config","tmpdir","ini","validation"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}