{"id":"f65982e3e6d8cf47","repo":"pypa/pip","slug":"invalid-sdist-filename-invalid-version-filenam","errorCode":null,"errorMessage":"Invalid sdist filename (invalid version): {filename!r}","messagePattern":"Invalid sdist filename \\(invalid version\\): (.+?)","errorType":"validation","errorClass":"InvalidSdistFilename","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/utils.py","lineNumber":292,"sourceCode":"        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\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":274,"sourceCodeEnd":297,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/packaging/utils.py#L274-L297","documentation":"Raised by `parse_sdist_filename` when the version segment (everything after the last dash in the stem) cannot be parsed as a PEP 440 version via `Version(version_part)`. The underlying `InvalidVersion` is caught and re-raised as `InvalidSdistFilename` with the cause chained (`from e`). Since PEP 440 versions contain no dashes, splitting on the last dash cleanly isolates the version string.","triggerScenarios":"A version segment like `v1.0`, `1.0.beta`, `20240305`, or any non-PEP-440 string after the last dash; sdist built from a project with a git-describe or date-based version that wasn't normalized.","commonSituations":"Projects setting `version` from `git describe --tags` (e.g. `v1.0-3-gabc`) without normalization; leading `v` in versions; date-only version schemes that violate PEP 440; renamed sdists.","solutions":["Normalize the project version to PEP 440 (drop leading `v`, use setuptools-scm's default normalization).","Validate the version in isolation with `Version(v)` to see the exact reason, then fix.","Rename the sdist to embed a valid version segment.","Rebuild the sdist with a compliant backend."],"exampleFix":"// before\nparse_sdist_filename('foo-v1.0.tar.gz')  # 'v1.0' invalid -> raises\n\n// after\nparse_sdist_filename('foo-1.0.tar.gz')","handlingStrategy":"try-catch","validationCode":"from pip._vendor.packaging.version import Version, InvalidVersion\n\ndef has_valid_sdist_version(filename: str) -> bool:\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    name_part, sep, version_part = stem.rpartition('-')\n    if not sep:\n        return False\n    try:\n        Version(version_part)\n        return True\n    except InvalidVersion:\n        return False","typeGuard":null,"tryCatchPattern":"from pip._vendor.packaging.utils import parse_sdist_filename, InvalidSdistFilename\n\ntry:\n    name, ver = parse_sdist_filename(filename)\nexcept InvalidSdistFilename as e:\n    if 'invalid version' in str(e):\n        # normalize the project version to PEP 440, then rebuild/rename\n        ...\n    raise","preventionTips":["Keep project versions PEP 440-compliant.","Normalize VCS-derived versions with setuptools-scm before building sdists.","Pre-validate the version segment in isolation with `Version()` for a precise error."],"tags":["python","packaging","utils","sdist","version","pep440"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}