Skip to content

extra names like "v8" that are also valid versions crash pip when installing #13349

@h4l

Description

@h4l

Description

pip is crashing when installing packages that use extra names that are also valid package versions, like v0 or v8. For example, pip install example[v8].

The crash is caused by the packaging package (that pip vendors as pip/_vendor/packaging). It mishandles the requirement in the package metadata that uses an extra name that's also a valid version:

Requires-Dist: typing-extensions; extra == 'v0'

I've contributed a fix for this upstream in pypa/packaging#883 and I'm reporting this issue with pip because I'm wanting to use this type of extra name with pip, and my PR in the packaging repo doesn't concretely demonstrate the bug being a problem in practice.

Expected behavior

pip should install the package without crashing. I've also tested this package with uv, and uv installs it correctly.

pip version

25.0.1

Python version

3.13

OS

Linux / Debian 12

How to Reproduce

I've created an example package to demo/reproduce this: https://github.com/h4l/v-extra-package-issue

$ pip install 'v-extra-example@git+https://github.com/h4l/v-extra-package-issue.git@main'

Or you can also check out that repo, build a wheel and install from the .whl file.

Output

$ pip --version
pip 25.0.1 from /workspaces/test-env/lib/python3.13/site-packages/pip (python 3.13)
$ pip install 'v-extra-example@git+https://github.com/h4l/v-extra-package-issue.git@main'
Collecting v-extra-example@ git+https://github.com/h4l/v-extra-package-issue.git@main
  Cloning https://github.com/h4l/v-extra-package-issue.git (to revision main) to /tmp/pip-install-39_iyhp3/v-extra-example_84a0e79200514316a5eabe83450d607d
  Running command git clone --filter=blob:none --quiet https://github.com/h4l/v-extra-package-issue.git /tmp/pip-install-39_iyhp3/v-extra-example_84a0e79200514316a5eabe83450d607d
  Resolved https://github.com/h4l/v-extra-package-issue.git to commit b79cc5327a64c6f5cae1e486ff9b9ee74378ecc8
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Preparing metadata (pyproject.toml) ... done
ERROR: Exception:
Traceback (most recent call last):
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_internal/cli/base_command.py", line 106, in _run_wrapper
    status = _inner_run()
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_internal/cli/base_command.py", line 97, in _inner_run
    return self.run(options, args)
           ~~~~~~~~^^^^^^^^^^^^^^^
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_internal/cli/req_command.py", line 67, in wrapper
    return func(self, options, args)
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_internal/commands/install.py", line 386, in run
    requirement_set = resolver.resolve(
        reqs, check_supported_wheels=not options.target_dir
    )
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 95, in resolve
    result = self._result = resolver.resolve(
                            ~~~~~~~~~~~~~~~~^
        collected.requirements, max_rounds=limit_how_complex_resolution_can_be
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers.py", line 546, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers.py", line 427, in resolve
    failure_causes = self._attempt_to_pin_criterion(name)
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers.py", line 239, in _attempt_to_pin_criterion
    criteria = self._get_updated_criteria(candidate)
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers.py", line 229, in _get_updated_criteria
    for requirement in self._p.get_dependencies(candidate=candidate):
                       ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/provider.py", line 247, in get_dependencies
    return [r for r in candidate.iter_dependencies(with_requires) if r is not None]
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 253, in iter_dependencies
    for r in requires:
             ^^^^^^^^
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_dists.py", line 225, in iter_dependencies
    elif not extras and req.marker.evaluate({"extra": ""}):
                        ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/packaging/markers.py", line 319, in evaluate
    return _evaluate_markers(
        self._markers, _repair_python_full_version(current_environment)
    )
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/packaging/markers.py", line 225, in _evaluate_markers
    groups[-1].append(_eval_op(lhs_value, op, rhs_value))
                      ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/packaging/markers.py", line 183, in _eval_op
    return spec.contains(lhs, prereleases=True)
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/packaging/specifiers.py", line 552, in contains
    normalized_item = _coerce_version(item)
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/packaging/specifiers.py", line 28, in _coerce_version
    version = Version(version)
  File "/workspaces/test-env/lib/python3.13/site-packages/pip/_vendor/packaging/version.py", line 202, in __init__
    raise InvalidVersion(f"Invalid version: {version!r}")
pip._vendor.packaging.version.InvalidVersion: Invalid version: ''

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions