{"record":{"id":"7a191f6c9b9d73ab","repo":"zylon-ai/private-gpt","slug":"unable-to-read-pkg-info-from-path","errorCode":null,"errorMessage":"Unable to read PKG-INFO from {path}","messagePattern":"Unable to read PKG-INFO from (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scripts/build_pip_index.py","lineNumber":56,"sourceCode":"\ndef read_wheel_metadata(path: Path) -> tuple[str, str | None]:\n    with zipfile.ZipFile(path) as archive:\n        metadata_name = next(\n            name for name in archive.namelist() if name.endswith(\".dist-info/METADATA\")\n        )\n        return parse_metadata(archive.read(metadata_name).decode())\n\n\ndef read_sdist_metadata(path: Path) -> tuple[str, str | None]:\n    with tarfile.open(path, \"r:gz\") as archive:\n        pkg_info = next(\n            member\n            for member in archive.getmembers()\n            if member.name == \"PKG-INFO\" or member.name.endswith(\"/PKG-INFO\")\n        )\n        fileobj = archive.extractfile(pkg_info)\n        if fileobj is None:\n            raise ValueError(f\"Unable to read PKG-INFO from {path}\")\n        return parse_metadata(fileobj.read().decode())\n\n\ndef read_distribution(path: Path) -> Distribution:\n    if path.suffix == \".whl\":\n        name, requires_python = read_wheel_metadata(path)\n    elif path.name.endswith(\".tar.gz\"):\n        name, requires_python = read_sdist_metadata(path)\n    else:\n        raise ValueError(f\"Unsupported distribution format: {path.name}\")\n\n    return Distribution(\n        name=name,\n        normalized_name=normalize_name(name),\n        filename=path.name,\n        requires_python=requires_python,\n        sha256=hashlib.sha256(path.read_bytes()).hexdigest(),\n    )","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/scripts/build_pip_index.py#L38-L74","documentation":"Raised by read_sdist_metadata in scripts/build_pip_index.py when a .tar.gz sdist contains a PKG-INFO member (found by name) but tarfile.extractfile() returns None for it. extractfile returns None only for non-regular members (directories, symlinks, devices), meaning the archive has a PKG-INFO entry that is not a plain file - a structurally invalid sdist.","triggerScenarios":"An sdist where PKG-INFO is a symlink to another file inside the tarball; a directory literally named PKG-INFO; a crafted or corrupted archive with a wrong member type; archives produced by tools that store PKG-INFO as a link target.","commonSituations":"Repackaged or manually edited sdists for internal indexes; security-hardened builds that convert files to symlinks; corrupted downloads where member types got mangled; artifacts from exotic packaging tools.","solutions":["Rebuild the sdist from source with a standard tool (python -m build / uv build) so PKG-INFO is a regular file","Inspect member types: tar -tvf dist.tar.gz | grep PKG-INFO (should start with '-', not 'l' or 'd')","Remove the offending sdist from the package dir and keep only well-formed wheels if the sdist is not required","If the archive is corrupted, re-download/re-generate it"],"exampleFix":"# before: PKG-INFO stored as symlink\nlrwxrwxrwx ... pkg-0.1.0/PKG-INFO -> setup.cfg\n\n# after: rebuilt archive has a regular file\n-rw-r--r-- ... pkg-0.1.0/PKG-INFO","handlingStrategy":"validation","validationCode":"import tarfile\n\ndef sdist_pkg_info_readable(path: str) -> bool:\n    with tarfile.open(path, \"r:gz\") as t:\n        for m in t.getmembers():\n            if m.name == \"PKG-INFO\" or m.name.endswith(\"/PKG-INFO\"):\n                return m.isfile()  # must be a regular file\n    return False","typeGuard":"null","tryCatchPattern":"try:\n    name, rp = read_sdist_metadata(p)\nexcept ValueError as e:\n    logger.warning(\"skipping bad sdist %s: %s\", p.name, e)\n    continue  # keep wheels, drop malformed sdists","preventionTips":["Build sdists with python -m build / uv build; never repackage by hand","Audit archives with tar -tvf and require PKG-INFO to be a regular file ('-' type)","Skip sdists entirely in the index if only wheels are needed","Treat symlinked PKG-INFO as a build-tool defect and file/fix it upstream"],"tags":["packaging","pip-index","sdist","tar"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}