{"record":{"id":"1c050aca6ea4a852","repo":"pypa/pip","slug":"cannot-determine-sdist-filename","errorCode":null,"errorMessage":"Cannot determine sdist filename","messagePattern":"Cannot determine sdist filename","errorType":"validation","errorClass":"PylockValidationError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/pylock.py","lineNumber":482,"sourceCode":"            name=_get(d, str, \"name\"),\n            upload_time=_get(d, datetime, \"upload-time\"),\n            url=_get(d, str, \"url\"),\n            path=_get(d, str, \"path\"),\n            size=_get(d, int, \"size\"),\n            hashes=_get_required_as(d, Mapping, _validate_hashes, \"hashes\"),  # type: ignore[type-abstract]\n        )\n        _validate_path_url(package_sdist.path, package_sdist.url)\n        return package_sdist\n\n    @property\n    def filename(self) -> str:\n        \"\"\"Get the filename of the sdist.\n\n        .. versionadded:: 26.1\n        \"\"\"\n        filename = self.name or _path_name(self.path) or _url_name(self.url)\n        if not filename:\n            raise PylockValidationError(\"Cannot determine sdist filename\")\n        return filename\n\n\n@dataclass(frozen=True, init=False)\nclass PackageWheel:\n    name: str | None = None\n    upload_time: datetime | None = None\n    url: str | None = None\n    path: str | None = None\n    size: int | None = None\n    hashes: Mapping[str, str]  # type: ignore[misc]\n\n    def __init__(\n        self,\n        *,\n        name: str | None = None,\n        upload_time: datetime | None = None,\n        url: str | None = None,","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/pylock.py#L464-L500","documentation":"Raised by the PackageSdist.filename property in pylock.py:480-483 when none of 'name', the basename of 'path', or the basename of 'url' yields a filename. The property is used inside Package._from_dict (pylock.py:635) to run parse_sdist_filename, and is also part of the public API.","triggerScenarios":"An sdist entry with no name, no path, and a url whose final path segment is empty (e.g. url = \"https://example.com/\" or a directory URL ending in '/').","commonSituations":"URL with a trailing slash and no filename component; forgetting to set 'name' when path/url lack a usable basename.","solutions":["Set name = \"pkg-1.0.tar.gz\" explicitly, or","Fix path/url so its last segment is the sdist filename (remove trailing slash)."],"exampleFix":"# before\n[[packages.sdist]]\nurl = \"https://example.com/\"\nhashes = { sha256 = \"...\" }\n# after\n[[packages.sdist]]\nurl = \"https://example.com/pkg-1.0.tar.gz\"\nhashes = { sha256 = \"...\" }","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse, unquote\n\ndef sdist_filename_resolvable(name, path, url) -> bool:\n    if name:\n        return True\n    if path and path.rsplit(\"/\", 1)[-1]:\n        return True\n    if url:\n        last = unquote(urlparse(url).path.rsplit(\"/\", 1)[-1])\n        return bool(last)\n    return False\n","typeGuard":null,"tryCatchPattern":"from packaging.pylock import Pylock, PylockValidationError\n\ntry:\n    Pylock.from_dict(d)\nexcept PylockValidationError as e:\n    ...\n","preventionTips":["Set an explicit 'name' on sdist entries when in doubt.","Ensure sdist URLs end in the .tar.gz filename, not a trailing slash."],"tags":["pylock","sdist","validation","filename"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}