pypa/pip · error · TypeError
Expected str, Requirement, or Distribution
Error message
Expected str, Requirement, or Distribution
What it means
Raised by the module-level get_distribution() when, after converting a string to a Requirement and resolving it via get_provider(), the result is not a Distribution instance. get_provider() returns an IResourceProvider for plain modules and a Distribution only for installed distributions; if you pass a module name that resolves to a resource provider but not a real distribution, the final isinstance check fails and TypeError is raised. The accepted inputs are str, Requirement, or an already-built Distribution.
Source
Thrown at src/pip/_vendor/pkg_resources/__init__.py:543
return True
# XXX Linux and other platforms' special cases should go here
return False
@overload
def get_distribution(dist: _DistributionT) -> _DistributionT: ...
@overload
def get_distribution(dist: _PkgReqType) -> Distribution: ...
def get_distribution(dist: Distribution | _PkgReqType) -> Distribution:
"""Return a current distribution object for a Requirement or string"""
if isinstance(dist, str):
dist = Requirement.parse(dist)
if isinstance(dist, Requirement):
# Bad type narrowing, dist has to be a Requirement here, so get_provider has to return Distribution
dist = get_provider(dist) # type: ignore[assignment]
if not isinstance(dist, Distribution):
raise TypeError("Expected str, Requirement, or Distribution", dist)
return dist
def load_entry_point(dist: _EPDistType, group: str, name: str) -> _ResolvedEntryPoint:
"""Return `name` entry point of `group` for `dist` or raise ImportError"""
return get_distribution(dist).load_entry_point(group, name)
@overload
def get_entry_map(
dist: _EPDistType, group: None = None
) -> dict[str, dict[str, EntryPoint]]: ...
@overload
def get_entry_map(dist: _EPDistType, group: str) -> dict[str, EntryPoint]: ...
def get_entry_map(dist: _EPDistType, group: str | None = None):
"""Return the entry point map for `group`, or the full entry map"""
return get_distribution(dist).get_entry_map(group)
View on GitHub (pinned to d7d0d0a394)
Solutions
- Pass a Distribution you already hold, or pass a project name string (e.g. 'requests') rather than an importable module dotted-path, so Requirement parsing + working_set lookup succeeds.
- Reinstall the target project with proper metadata (pip install -e . or pip install <pkg>) so an .egg-info/.dist-info directory exists and get_provider returns a Distribution.
- Catch TypeError around get_distribution and fall back to importlib.metadata.metadata() or importlib.metadata.distribution() for lookups.
Example fix
// before
import pkg_resources
dist = pkg_resources.get_distribution("my_namespace.sub") # TypeError if not a real dist
// after
from importlib import metadata
dist = metadata.distribution("my-namespace-sub") # works for installed dist metadata Defensive patterns
Strategy: type-guard
Validate before calling
import pkg_resources
from pkg_resources import Distribution, Requirement
def safe_get_distribution(dist):
if isinstance(dist, Distribution):
return dist
if isinstance(dist, str):
# pass project name, not a dotted module path
return pkg_resources.get_distribution(dist)
if isinstance(dist, Requirement):
return pkg_resources.get_distribution(dist)
raise TypeError('pass a str project name, Requirement, or Distribution') Type guard
from pkg_resources import Distribution, Requirement
def is_distribution_input(x):
return isinstance(x, (str, Requirement, Distribution)) Try / catch
try:
dist = pkg_resources.get_distribution(target)
except TypeError as e:
if 'Expected str, Requirement, or Distribution' in str(e):
# fall back to importlib.metadata for code-only modules
from importlib import metadata
dist = metadata.distribution(target)
else:
raise Prevention
- Pass project names (e.g. 'requests') rather than importable dotted module paths.
- Ensure the target is installed with metadata (pip install) before querying.
- Prefer importlib.metadata for new code; it has clearer not-found semantics (PackageNotFoundError).
When it happens
Trigger: Calling pkg_resources.get_distribution('some.module') where 'some.module' is importable as code but is not backed by installed dist metadata (e.g. a namespace package, a module added to sys.path directly, a PEP 660 editable install without proper metadata, or a module whose loader type was only registered with a plain provider). Also when passing a Distribution subclass instance whose type is not recognized by get_provider's registry.
Common situations: Querying metadata for a project installed in development/editable mode without a proper .egg-info/.dist-info, a namespace package, or a module living in a flat directory on sys.path. Also after a partially-failed uninstall that left code but removed metadata.
Related errors
- Error decoding metadata for {self._wheel_name}: {e} in {name
- Script {script!r} not found in metadata at {self.egg_info!r}
- `base` parameter in `_fn` is `None`. Either override this me
- No metadata except PKG-INFO is available
- Invalid group name
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/a68ca9a42b3edc94.json.
Report an issue: GitHub.