{"record":{"id":"b9b482cf29bc2989","repo":"pypa/pip","slug":"invalid-sdist-filename-filename-r","errorCode":null,"errorMessage":"Invalid sdist filename: {filename!r}","messagePattern":"Invalid sdist filename: (.+?)","errorType":"validation","errorClass":"InvalidSdistFilename","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/utils.py","lineNumber":355,"sourceCode":"       Raises :class:`InvalidSdistFilename` on an empty project name.\n\n    .. _Source distribution format: https://packaging.python.org/specifications/source-distribution-format/#source-distribution-file-name\n    \"\"\"\n    if filename.endswith(\".tar.gz\"):\n        file_stem = filename[: -len(\".tar.gz\")]\n    elif filename.endswith(\".zip\"):\n        file_stem = filename[: -len(\".zip\")]\n    else:\n        raise InvalidSdistFilename(\n            f\"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):\"\n            f\" {filename!r}\"\n        )\n\n    # We are requiring a PEP 440 version, which cannot contain dashes,\n    # so we split on the last dash.\n    name_part, sep, version_part = file_stem.rpartition(\"-\")\n    if not sep:\n        raise InvalidSdistFilename(f\"Invalid sdist filename: {filename!r}\")\n    if not name_part:\n        raise InvalidSdistFilename(\n            f\"Invalid sdist filename (empty project name): {filename!r}\"\n        )\n\n    name = canonicalize_name(name_part)\n\n    try:\n        version = Version(version_part)\n    except InvalidVersion as e:\n        raise InvalidSdistFilename(\n            f\"Invalid sdist filename (invalid version): {filename!r}\"\n        ) from e\n\n    return (name, version)\n","sourceCodeStart":337,"sourceCodeEnd":371,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/utils.py#L337-L371","documentation":"Raised by parse_sdist_filename() when the stem (after removing the extension) contains no dash at all (utils.py:353-355). The parser uses rpartition('-') to split name from version; if no dash exists, sep is empty, meaning there is no name-version boundary. The exception class is InvalidSdistFilename.","triggerScenarios":"A filename with no dash separating the project name from the version, e.g. parse_sdist_filename('foo10.tar.gz') where the stem 'foo10' has no dash.","commonSituations":"A filename where the name and version were concatenated without a dash, or a stray file that happens to have a .tar.gz extension but is not a valid sdist.","solutions":["Ensure the filename contains a dash between the project name and the version.","Rename the file to follow the {name}-{version}.tar.gz convention.","Verify the source of the filename is an actual PyPI-style sdist."],"exampleFix":"// before\nparse_sdist_filename('foo10.tar.gz')\n// after\nparse_sdist_filename('foo-1.0.tar.gz')","handlingStrategy":"validation","validationCode":"def safe_parse_sdist(filename: str):\n    stem = filename[:-7] if filename.endswith(\".tar.gz\") else filename[:-4]\n    if \"-\" not in stem:\n        raise ValueError(f\"Sdist filename has no name-version dash: {filename!r}\")\n    return parse_sdist_filename(filename)","typeGuard":"def has_sdist_dash(filename: str) -> bool:\n    if not isinstance(filename, str):\n        return False\n    if filename.endswith(\".tar.gz\"):\n        stem = filename[:-7]\n    elif filename.endswith(\".zip\"):\n        stem = filename[:-4]\n    else:\n        return False\n    return \"-\" in stem","tryCatchPattern":"from packaging.utils import InvalidSdistFilename\n\ntry:\n    name, ver = parse_sdist_filename(filename)\nexcept InvalidSdistFilename as e:\n    if \"Invalid sdist filename:\" in str(e) and \"empty\" not in str(e):\n        logger.error(\"No name-version separator in: %s\", filename)\n    raise","preventionTips":["Ensure the sdist filename contains a dash between name and version","Follow the {name}-{version}.tar.gz convention","Validate that the stem contains at least one dash before parsing"],"tags":["sdist","filename","packaging"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}