pypa/pip · error · NoneMetadataError

None metadata found for distribution

Error message

None {metadata_name} metadata found for distribution: {dist}

What it means

Raised as NoneMetadataError(self, name) from Distribution.read_text in pkg_resources.py:206-213. It indicates an inconsistent state: has_metadata(name) returned True (the metadata file is listed) but get_metadata(name) returned None (no content retrievable) — pip cannot proceed reading a metadata file that claims to exist yet yields nothing.

Solutions

  1. Reinstall the affected package to regenerate a consistent metadata directory.
  2. Delete the broken .egg-info/.dist-info directory so it is not discovered, then reinstall.
  3. If building, ensure the backend always writes complete metadata files.
Defensive patterns

Strategy: validation

Validate before calling

// Before read_text, confirm metadata is consistently present and non-empty:
if dist.has_metadata(name):
    assert dist.get_metadata(name) is not None, f'{name} listed but empty'
content = dist.read_text(name)

Try / catch

from pip._internal.exceptions import NoneMetadataError
try:
    content = dist.read_text('METADATA')
except NoneMetadataError:
    # reinstall the package to repair metadata
    ...

Prevention

When it happens

Trigger: Calling Distribution.read_text on a pkg_resources Distribution where has_metadata reports the file present but get_metadata yields None — e.g. a pathological metadata provider or a half-written egg-info/dist-info.

Common situations: A distribution whose egg-info/dist-info directory lists METADATA/PKG-INFO in its index but the actual file is empty/missing due to a crashed or interrupted install; a buggy custom metadata provider.

Related errors


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

Appendix: source

Thrown at src/pip/_internal/metadata/pkg_resources.py:212

        return parse_version(self._dist.version)

    @property
    def raw_version(self) -> str:
        return self._dist.version

    def is_file(self, path: InfoPath) -> bool:
        return self._dist.has_metadata(str(path))

    def iter_distutils_script_names(self) -> Iterator[str]:
        yield from self._dist.metadata_listdir("scripts")

    def read_text(self, path: InfoPath) -> str:
        name = str(path)
        if not self._dist.has_metadata(name):
            raise FileNotFoundError(name)
        content = self._dist.get_metadata(name)
        if content is None:
            raise NoneMetadataError(self, name)
        return content

    def iter_entry_points(self) -> Iterable[BaseEntryPoint]:
        try:
            entry_map = self._dist.get_entry_map()
        except ValueError as e:
            raise InstallationError(
                f"Error parsing entry points for {self.raw_name}: {e}"
            ) from e
        for group, entries in entry_map.items():
            for name, entry_point in entries.items():
                name, _, value = str(entry_point).partition("=")
                yield EntryPoint(name=name.strip(), value=value.strip(), group=group)

    def _metadata_impl(self) -> email.message.Message:
        """
        :raises NoneMetadataError: if the distribution reports `has_metadata()`
            True but `get_metadata()` returns None.

View on GitHub (pinned to f399c37189)