pypa/pip · error · KeyError

No metadata except PKG-INFO is available

Error message

No metadata except PKG-INFO is available

What it means

Raised as KeyError by FileMetadata.get_metadata(name). FileMetadata is an EmptyProvider subclass backed by a single file path (a PKG-INFO file); it deliberately serves only the 'PKG-INFO' metadata name and rejects any other name. has_metadata() on the same class returns True only for name == 'PKG-INFO'. It is constructed when only a bare PKG-INFO path is available (e.g. an old-style source dist or a single metadata file).

Source

Thrown at src/pip/_vendor/pkg_resources/__init__.py:2171

        metadata = FileMetadata("/path/to/PKG-INFO")

    This provider rejects all data and metadata requests except for PKG-INFO,
    which is treated as existing, and will be the contents of the file at
    the provided location.
    """

    def __init__(self, path: StrPath):
        self.path = path

    def _get_metadata_path(self, name):
        return self.path

    def has_metadata(self, name: str) -> bool:
        return name == 'PKG-INFO' and os.path.isfile(self.path)

    def get_metadata(self, name: str):
        if name != 'PKG-INFO':
            raise KeyError("No metadata except PKG-INFO is available")

        with open(self.path, encoding='utf-8', errors="replace") as f:
            metadata = f.read()
        self._warn_on_replacement(metadata)
        return metadata

    def _warn_on_replacement(self, metadata):
        replacement_char = '�'
        if replacement_char in metadata:
            tmpl = "{self.path} could not be properly decoded in UTF-8"
            msg = tmpl.format(**locals())
            warnings.warn(msg)

    def get_metadata_lines(self, name: str) -> Iterator[str]:
        return yield_lines(self.get_metadata(name))


class PathMetadata(DefaultProvider):

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Guard with has_metadata() first: `if dist.has_metadata(name): dist.get_metadata(name)`.
  2. If you need full metadata, point the distribution at a complete .dist-info/.egg-info directory (use PathMetadata or DistInfoMetadata) instead of a single PKG-INFO file.
  3. Use importlib.metadata, which returns at least core metadata for installed dists and degrades more gracefully.

Example fix

// before
ep_text = dist.get_metadata('entry_points.txt')  # KeyError: only PKG-INFO available

// after
if dist.has_metadata('entry_points.txt'):
    ep_text = dist.get_metadata('entry_points.txt')
else:
    ep_text = ''  # no entry points metadata present
Defensive patterns

Strategy: validation

Validate before calling

def safe_get_metadata(dist, name):
    if dist.has_metadata(name):
        return dist.get_metadata(name)
    return None  # or raise a domain-specific error

Type guard

def metadata_available(dist, name) -> bool:
    return dist.has_metadata(name)

Try / catch

try:
    text = dist.get_metadata(name)
except KeyError as e:
    if 'PKG-INFO' in str(e):
        text = None  # only PKG-INFO is available on FileMetadata
    else:
        raise

Prevention

When it happens

Trigger: Calling dist.get_metadata('entry_points.txt') (or RECORD, requires.txt, etc.) on a Distribution whose metadata provider is a FileMetadata — i.e. it was built from a lone PKG-INFO file rather than a full .egg-info/.dist-info directory. Any name != 'PKG-INFO' raises KeyError.

Common situations: Old-style distributions or sdist layouts that ship only a PKG-INFO; tools that construct a Distribution from a single metadata file; querying rich metadata (entry points, dependencies) from a source that never had it.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/c6f6e1e20c4bb11b.json. Report an issue: GitHub.