pypa/pip · error · DistributionNotFound
No matching distribution found for {req}
Error message
No matching distribution found for {req} What it means
DistributionNotFound raised at the end of find_best_candidate when no installable candidate was found AND nothing satisfying is already installed. The classic 'No matching distribution found for X' message; it logs the available versions (or 'none') before raising.
Source
Thrown at src/pip/_internal/index/package_finder.py:1057
if installed_version is None and best_candidate is None:
# Check if only final releases are allowed for this package
version_type = "version"
if self.release_control is not None:
allows_pre = self.release_control.allows_prereleases(
canonicalize_name(name)
)
if allows_pre is False:
version_type = "final version"
logger.critical(
"Could not find a %s that satisfies the requirement %s "
"(from versions: %s)",
version_type,
req,
_format_versions(best_candidate_result.all_candidates),
)
raise DistributionNotFound(f"No matching distribution found for {req}")
def _should_install_candidate(
candidate: InstallationCandidate | None,
) -> TypeGuard[InstallationCandidate]:
if installed_version is None:
return True
if best_candidate is None:
return False
return best_candidate.version > installed_version
if not upgrade and installed_version is not None:
if _should_install_candidate(best_candidate):
logger.debug(
"Existing installed version (%s) satisfies requirement "
"(most up-to-date version is %s)",
installed_version,
best_candidate.version,
)View on GitHub (pinned to d7d0d0a394)
Solutions
- Verify the package name spelling and that it exists on the configured index (pip index versions <name> or check pypi.org).
- Loosen the version specifier (drop ==, widen >=) so an existing release can match.
- Check 'from versions:' in the log - if 'none', the index returned nothing (network/index URL issue or fully-incompatible requires-python).
- Allow sdists by removing --only-binary, or allow prereleases with --pre if only pre-releases exist.
Example fix
# before pip install 'somepkg==1.2.4' # version does not exist # after pip index versions somepkg # see what exists pip install 'somepkg>=1.2,<2' # pick an existing release
Defensive patterns
Strategy: try-catch
Validate before calling
import subprocess, json, urllib.request
# 1) check package exists
try:
json.load(urllib.request.urlopen(f'https://pypi.org/pypi/{name}/json'))
except urllib.error.HTTPError:
print('package not found on index')
# 2) check specifier has any match
from packaging.requirements import Requirement
req = Requirement(spec)
releases = [Version(v) for v in data['releases']]
if not any(req.specifier.contains(v, prereleases=True) for v in releases):
print('no version satisfies', spec) Type guard
def requirement_satisfiable(name: str, spec: str) -> bool:
import urllib.request, json
from packaging.requirements import Requirement
from packaging.version import Version
d = json.load(urllib.request.urlopen(f'https://pypi.org/pypi/{name}/json'))
req = Requirement(f'{name}{spec}')
return any(req.specifier.contains(Version(v), prereleases=True)
for v in d['releases']) Try / catch
from pip._internal.exceptions import DistributionNotFound
try:
pip.main(['install', req])
except DistributionNotFound as e:
# log; suggest checking name/version/Python compat
... Prevention
- Verify package names with 'pip index versions'.
- Loosen version specifiers and avoid nonexistent exact pins.
- Confirm Python version compatibility (requires-python).
- Allow sdist/prereleases when wheels/prereleases are the only option.
When it happens
Trigger: Reached when installed_version is None and best_candidate is None after filtering all candidates by platform tags, requires-python, format control, prerelease policy, and hashes. Typo in package name, no compatible wheel/sdist on the index, or all versions excluded by version specifiers.
Common situations: Misspelled package name; requiring a version specifier that no release satisfies (e.g. '==1.2.4' that doesn't exist); Python version too new/old for every release (requires-python excludes all); index unreachable or empty; --only-binary with no wheel available; offline install with no local index.
Related errors
- No matching distribution found for {query}
- You need to specify exactly one argument
- <dynamic: upload-time missing detail>
- Could not install locked package {project_name!r} from {lock
- Multiple locked links provided for {project_name}: {self._lo
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/bae81a6befac1d67.json.
Report an issue: GitHub.