pypa/pip · error · TypeError

Expected str, Requirement, or Distribution

Error message

Expected str, Requirement, or Distribution

What it means

Raised by pkg_resources.get_distribution() when the argument is not a str, a Requirement, nor a Distribution. The function accepts a project name string, a requirement string, a Requirement object, or an existing Distribution; after normalization, if the result is none of these, TypeError is raised. This is a type-contract violation by the caller.

Solutions

  1. Check that the argument is a str before calling: assert isinstance(name, str).
  2. Fix the upstream code to always supply a non-None package name string.
  3. Use a type guard or explicit conversion to str before calling get_distribution().

Example fix

// before
dist = get_distribution(maybe_none)
// after
if maybe_none is None:
    raise ValueError('package name is required')
dist = get_distribution(maybe_none)
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(dist, (str, Requirement, Distribution)):
    raise TypeError(f'Expected str/Requirement/Distribution, got {type(dist)}')
get_distribution(dist)

Type guard

import pkg_resources
def is_valid_dist_arg(d) -> bool:
    return isinstance(d, (str, pkg_resources.Requirement, pkg_resources.Distribution))

Try / catch

try:
    d = get_distribution(arg)
except TypeError:
    # caller passed a wrong type
    d = None

Prevention

When it happens

Trigger: Calling get_distribution(None), get_distribution(123), get_distribution(['flask']), or any value whose type is not str/Requirement/Distribution.

Common situations: A variable that was expected to hold a package name string but is None (e.g. a missing config key); passing a list or dict where a scalar name was expected; a refactoring that changed the type flowing into get_distribution.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/a68ca9a42b3edc94. Report an issue: GitHub.

Appendix: 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 f399c37189)