{"record":{"id":"1b0e0992a02c901b","repo":"pytest-dev/pytest","slug":"missing-required-plugins","errorCode":null,"errorMessage":"Missing required plugins: {}","messagePattern":"Missing required plugins: (.+?)","errorType":"exception","errorClass":"UsageError","httpStatus":null,"severity":"error","filePath":"src/_pytest/config/__init__.py","lineNumber":1555,"sourceCode":"        plugin_dist_info = {dist.project_name: dist.version for _, dist in plugin_info}\n\n        missing_plugins = []\n        for required_plugin in required_plugins:\n            try:\n                req = Requirement(required_plugin)\n            except InvalidRequirement:\n                missing_plugins.append(required_plugin)\n                continue\n\n            if req.name not in plugin_dist_info:\n                missing_plugins.append(required_plugin)\n            elif not req.specifier.contains(\n                Version(plugin_dist_info[req.name]), prereleases=True\n            ):\n                missing_plugins.append(required_plugin)\n\n        if missing_plugins:\n            raise UsageError(\n                \"Missing required plugins: {}\".format(\", \".join(missing_plugins)),\n            )\n\n    def _warn_or_fail_if_strict(self, message: str) -> None:\n        strict_config = self.getini(\"strict_config\")\n        if strict_config is None:\n            strict_config = self.getini(\"strict\")\n        if strict_config:\n            raise UsageError(message)\n\n        self.issue_config_time_warning(PytestConfigWarning(message), stacklevel=3)\n\n    def _get_unknown_ini_keys(self) -> set[str]:\n        known_keys = self._parser._inidict.keys() | self._parser._ini_aliases.keys()\n        return self._inicfg.keys() - known_keys\n\n    def parse(self, args: list[str], addopts: bool = True) -> None:\n        # Parse given cmdline arguments into this config object.","sourceCodeStart":1537,"sourceCodeEnd":1573,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/config/__init__.py#L1537-L1573","documentation":"Raised by _validate_plugins() (src/_pytest/config/__init__.py:1554-1557) when one or more entries in the `required_plugins` ini option cannot be matched against the active environment's installed plugin distributions. The check at config/__init__.py:1540-1552 parses each requirement with packaging.requirement.Requirement, then verifies the name exists in pluginmanager.list_plugin_distinfo() and that the installed version satisfies req.specifier. Failures accumulate and raise UsageError with the joined list.","triggerScenarios":"Setting `required_plugins = pytest-xdist>=3 pytest-cov` in pyproject.toml/pytest.ini when one is missing or below the pinned version. config/__init__.py:1543 catches InvalidRequirement (malformed spec) and config/__init__.py:1547-1552 handle missing-name and version-mismatch.","commonSituations":"CI runs without a plugin the project requires; bumping a version pin without reinstalling; typo in the plugin name; package installed under a different distribution name than the requirement (e.g. pytest-asyncio vs async-plugin aliases).","solutions":["pip install every plugin listed in the error message, honoring the version specifier","Lower or relax the version pin in required_plugins if the newer version is acceptable","Remove the entry from required_plugins if it is no longer actually used","Verify the distribution name matches (use `pip show <name>` to confirm project_name)"],"exampleFix":"// before\n# pyproject.toml\n[tool.pytest.ini_options]\nrequired_plugins = ['pytest-xdist>=4.0']\n// after\npip install 'pytest-xdist>=4.0'\n# or relax\nrequired_plugins = ['pytest-xdist>=3.0']","handlingStrategy":"validation","validationCode":"from packaging.requirements import Requirement\nfrom importlib.metadata import distributions\ndist_names = {d.metadata['Name'] for d in distributions()}\nfor req_str in required_plugins:\n    r = Requirement(req_str)\n    if r.name not in dist_names:\n        print(f'Missing: {req_str}')","typeGuard":"def requirement_satisfied(req_str: str, installed: dict[str,str]) -> bool:\n    from packaging.requirements import Requirement\n    from packaging.version import Version\n    r = Requirement(req_str)\n    return r.name in installed and r.specifier.contains(Version(installed[r.name]), prereleases=True)","tryCatchPattern":"from _pytest.config import UsageError\ntry:\n    pytest.main([])\nexcept UsageError as e:\n    if 'Missing required plugins' in str(e):\n        import subprocess; subprocess.check_call(['pip','install',*missing])","preventionTips":["Install required_plugins in CI before invoking pytest","Use exact distribution names (pip show <name> to confirm project_name)","Keep version pins achievable in your lowest supported environment"],"tags":["plugin","config","dependency","validation"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}