pypa/pip · error · InvalidSdistFilename
Invalid sdist filename: {filename!r}
Error message
Invalid sdist filename: {filename!r} What it means
Raised by `parse_sdist_filename` when, after stripping the `.tar.gz`/`.zip` extension, `file_stem.rpartition('-')` finds no dash at all (`sep == ''`). A valid sdist filename must contain at least one dash separating the project name from the version (e.g. `foo-1.0`). With no dash there is no name/version boundary to split on.
Source
Thrown at src/pip/_vendor/packaging/utils.py:285
True
.. _Source distribution format: https://packaging.python.org/specifications/source-distribution-format/#source-distribution-file-name
"""
if filename.endswith(".tar.gz"):
file_stem = filename[: -len(".tar.gz")]
elif filename.endswith(".zip"):
file_stem = filename[: -len(".zip")]
else:
raise InvalidSdistFilename(
f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):"
f" {filename!r}"
)
# We are requiring a PEP 440 version, which cannot contain dashes,
# so we split on the last dash.
name_part, sep, version_part = file_stem.rpartition("-")
if not sep:
raise InvalidSdistFilename(f"Invalid sdist filename: {filename!r}")
name = canonicalize_name(name_part)
try:
version = Version(version_part)
except InvalidVersion as e:
raise InvalidSdistFilename(
f"Invalid sdist filename (invalid version): {filename!r}"
) from e
return (name, version)
View on GitHub (pinned to d7d0d0a394)
Solutions
- Rename the file to the standard `name-version.tar.gz` (or `.zip`) form.
- Rebuild the sdist with a compliant backend, which always emits `name-version`.
- Pre-validate that the stem contains a dash before calling.
- If you only have a name and version separately, construct the `Version` directly instead of parsing a filename.
Example fix
// before
parse_sdist_filename('fooonly.tar.gz') # no dash -> raises
// after
parse_sdist_filename('fooonly-1.0.tar.gz') Defensive patterns
Strategy: validation
Validate before calling
def has_name_version_dash(filename: str) -> bool:
if filename.endswith('.tar.gz'):
stem = filename[:-len('.tar.gz')]
elif filename.endswith('.zip'):
stem = filename[:-len('.zip')]
else:
return False
return '-' in stem Type guard
def is_splitable_sdist(filename: object) -> bool:
if not isinstance(filename, str):
return False
if filename.endswith('.tar.gz'):
stem = filename[:-7]
elif filename.endswith('.zip'):
stem = filename[:-4]
else:
return False
return '-' in stem Try / catch
from pip._vendor.packaging.utils import parse_sdist_filename, InvalidSdistFilename
try:
name, ver = parse_sdist_filename(filename)
except InvalidSdistFilename as e:
if 'Invalid sdist filename:' in str(e) and 'extension' not in str(e):
# no dash; reconstruct name-version from metadata
...
raise Prevention
- Ensure sdists are named `name-version.tar.gz` with at least one dash.
- Use a compliant backend to build sdists so the filename is always correct.
- Pre-check that the stem contains a dash before parsing.
When it happens
Trigger: A filename like `foobar.tar.gz` (no dash), or any single-token stem; the parser cannot tell where the name ends and the version begins.
Common situations: A malformed/renamed sdist; a project with no version embedded in the filename; an artifact whose name was collapsed.
Related errors
- Invalid sdist filename (extension must be '.tar.gz' or '.zip
- Invalid wheel filename (extension must be '.whl'): {filename
- Invalid wheel filename (wrong number of parts): {filename!r}
- Invalid project name: {filename!r}
- Invalid build number: {build_part} in {filename!r}
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/b9b482cf29bc2989.json.
Report an issue: GitHub.