pytest-dev/pytest · error · UsageError
Missing required plugins
Error message
Missing required plugins: {} What it means
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.
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)
Example fix
// before # pyproject.toml [tool.pytest.ini_options] required_plugins = ['pytest-xdist>=4.0'] // after pip install 'pytest-xdist>=4.0' # or relax required_plugins = ['pytest-xdist>=3.0']
Defensive patterns
Strategy: validation
Validate before calling
from packaging.requirements import Requirement
from importlib.metadata import distributions
dist_names = {d.metadata['Name'] for d in distributions()}
for req_str in required_plugins:
r = Requirement(req_str)
if r.name not in dist_names:
print(f'Missing: {req_str}') Type guard
def requirement_satisfied(req_str: str, installed: dict[str,str]) -> bool:
from packaging.requirements import Requirement
from packaging.version import Version
r = Requirement(req_str)
return r.name in installed and r.specifier.contains(Version(installed[r.name]), prereleases=True) Try / catch
from _pytest.config import UsageError
try:
pytest.main([])
except UsageError as e:
if 'Missing required plugins' in str(e):
import subprocess; subprocess.check_call(['pip','install',*missing]) Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Error importing plugin
- plugin cannot be disabled
- Plugins may be specified as a sequence or a ','-separated…
- Blocking conftest files using -p is not supported: -p no
- help argument cannot be None for
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/1b0e0992a02c901b.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/config/__init__.py:1555
plugin_dist_info = {dist.project_name: dist.version for _, dist in plugin_info}
missing_plugins = []
for required_plugin in required_plugins:
try:
req = Requirement(required_plugin)
except InvalidRequirement:
missing_plugins.append(required_plugin)
continue
if req.name not in plugin_dist_info:
missing_plugins.append(required_plugin)
elif not req.specifier.contains(
Version(plugin_dist_info[req.name]), prereleases=True
):
missing_plugins.append(required_plugin)
if missing_plugins:
raise UsageError(
"Missing required plugins: {}".format(", ".join(missing_plugins)),
)
def _warn_or_fail_if_strict(self, message: str) -> None:
strict_config = self.getini("strict_config")
if strict_config is None:
strict_config = self.getini("strict")
if strict_config:
raise UsageError(message)
self.issue_config_time_warning(PytestConfigWarning(message), stacklevel=3)
def _get_unknown_ini_keys(self) -> set[str]:
known_keys = self._parser._inidict.keys() | self._parser._ini_aliases.keys()
return self._inicfg.keys() - known_keys
def parse(self, args: list[str], addopts: bool = True) -> None:
# Parse given cmdline arguments into this config object.View on GitHub (pinned to 0d6fbdeffa)