{"id":"c6f6e1e20c4bb11b","repo":"pypa/pip","slug":"no-metadata-except-pkg-info-is-available","errorCode":null,"errorMessage":"No metadata except PKG-INFO is available","messagePattern":"No metadata except PKG-INFO is available","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pkg_resources/__init__.py","lineNumber":2171,"sourceCode":"        metadata = FileMetadata(\"/path/to/PKG-INFO\")\n\n    This provider rejects all data and metadata requests except for PKG-INFO,\n    which is treated as existing, and will be the contents of the file at\n    the provided location.\n    \"\"\"\n\n    def __init__(self, path: StrPath):\n        self.path = path\n\n    def _get_metadata_path(self, name):\n        return self.path\n\n    def has_metadata(self, name: str) -> bool:\n        return name == 'PKG-INFO' and os.path.isfile(self.path)\n\n    def get_metadata(self, name: str):\n        if name != 'PKG-INFO':\n            raise KeyError(\"No metadata except PKG-INFO is available\")\n\n        with open(self.path, encoding='utf-8', errors=\"replace\") as f:\n            metadata = f.read()\n        self._warn_on_replacement(metadata)\n        return metadata\n\n    def _warn_on_replacement(self, metadata):\n        replacement_char = '�'\n        if replacement_char in metadata:\n            tmpl = \"{self.path} could not be properly decoded in UTF-8\"\n            msg = tmpl.format(**locals())\n            warnings.warn(msg)\n\n    def get_metadata_lines(self, name: str) -> Iterator[str]:\n        return yield_lines(self.get_metadata(name))\n\n\nclass PathMetadata(DefaultProvider):","sourceCodeStart":2153,"sourceCodeEnd":2189,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pkg_resources/__init__.py#L2153-L2189","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Guard with has_metadata() first: `if dist.has_metadata(name): dist.get_metadata(name)`.","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.","Use importlib.metadata, which returns at least core metadata for installed dists and degrades more gracefully."],"exampleFix":"// before\nep_text = dist.get_metadata('entry_points.txt')  # KeyError: only PKG-INFO available\n\n// after\nif dist.has_metadata('entry_points.txt'):\n    ep_text = dist.get_metadata('entry_points.txt')\nelse:\n    ep_text = ''  # no entry points metadata present","handlingStrategy":"validation","validationCode":"def safe_get_metadata(dist, name):\n    if dist.has_metadata(name):\n        return dist.get_metadata(name)\n    return None  # or raise a domain-specific error","typeGuard":"def metadata_available(dist, name) -> bool:\n    return dist.has_metadata(name)","tryCatchPattern":"try:\n    text = dist.get_metadata(name)\nexcept KeyError as e:\n    if 'PKG-INFO' in str(e):\n        text = None  # only PKG-INFO is available on FileMetadata\n    else:\n        raise","preventionTips":["Always guard get_metadata with has_metadata(name).","Point distributions at full .dist-info/.egg-info dirs, not lone PKG-INFO files.","Use importlib.metadata for installed-distribution metadata lookups."],"tags":["pkg-resources","metadata","file-metadata","key-error","pkg-info"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}