pypa/pip · error · TypeError
expected VersionRange, got {type(other).__name__}
Error message
expected VersionRange, got {type(other).__name__} What it means
TypeError raised by VersionRange._check_policy_compat (invoked by union, intersection, difference, issubset, isdisjoint, etc.) when the 'other' operand is not a VersionRange. VersionRange set-algebra is only defined between two VersionRange instances; mixing in a SpecifierSet, str, or set is a type error.
Source
Thrown at src/pip/_vendor/packaging/ranges.py:1087
away from full bounds it survives only on empty-bounds ranges, where
it keeps ``~~full() == full()`` and union idempotent.
"""
return self._admit_arbitrary and self._bounds == FULL_RANGE
def _is_plain(self) -> bool:
"""True when membership is decided by ``_bounds`` alone, enabling the
bounds-only fast paths in :meth:`is_subset` and :meth:`is_disjoint`.
"""
return (
not self._has_literals()
and not self._admit_arbitrary
and self._prereleases_configured is not False
)
def _check_policy_compat(self, other: VersionRange) -> None:
"""Refuse combining ranges with different pre-release policies."""
if not isinstance(other, VersionRange):
raise TypeError(f"expected VersionRange, got {type(other).__name__}")
if self._prereleases_configured != other._prereleases_configured:
raise ValueError(
"Cannot combine VersionRange operands with different "
f"pre-release policies: {self._prereleases_configured!r} "
f"and {other._prereleases_configured!r}"
)
def _merged_region(self, other: VersionRange) -> tuple[Interval, ...]:
"""Union of ``self`` and ``other``'s opt-in regions.
Used by :meth:`union` and :meth:`intersection`; :meth:`_build` clips the
merge to the result bounds. A configured operand carries an empty region,
so it contributes nothing to the merge.
"""
# Reuse an operand's canonical tuple when only one side has a region;
# an empty side contributes nothing to the union.
if not other._pre_region:
return self._pre_regionView on GitHub (pinned to f399c37189)
Solutions
- Convert the non-range operand to a VersionRange first: SpecifierSet(s).to_range() for a specifier, VersionRange.singleton(v) for a single version.
- If you hold a SpecifierSet, call .to_range() once and reuse the resulting VersionRange in all set operations.
- Type-narrow inputs in shared helpers so only VersionRange reaches the set-algebra methods.
- If the operand is a plain string meant as an exact match, use VersionRange.singleton(string).
Example fix
# before
from packaging.specifiers import SpecifierSet
r = SpecifierSet('>=1.0').to_range()
combined = r.union(SpecifierSet('<2.0')) # TypeError
# after
combined = r.union(SpecifierSet('<2.0').to_range()) Defensive patterns
Strategy: type-guard
Validate before calling
null
Type guard
from packaging.ranges import VersionRange
from packaging.specifiers import SpecifierSet
def as_version_range(x) -> VersionRange:
if isinstance(x, VersionRange):
return x
if isinstance(x, SpecifierSet):
return x.to_range()
if isinstance(x, str):
return SpecifierSet(x).to_range()
raise TypeError(f"expected VersionRange/SpecifierSet/str, got {type(x).__name__}")
# then: a.union(as_version_range(other)) Try / catch
try:
combined = a.union(b)
except TypeError as e:
# convert b to a VersionRange via as_version_range() and retry
raise Prevention
- Convert every SpecifierSet to a VersionRange once and pass ranges around thereafter.
- Type-narrow inputs to set-algebra helpers so only VersionRange reaches union/intersection/etc.
- Do not pass specifier strings directly to set operations; build a range first.
When it happens
Trigger: Calling e.g. range_a.union(specifierset) or range_a.intersection('>=1.0') — passing anything that is not an instance of VersionRange. The guard 'isinstance(other, VersionRange)' fails and raises with the actual type name.
Common situations: Refactoring code that previously combined SpecifierSets directly; passing a specifier string assuming implicit conversion; a generic helper that accepts both types and forgets to convert.
Related errors
- Cannot combine VersionRange operands with different pre-rele
- VersionRange.contains() expected str or Version, got {type(i
- cannot create 'VersionRange' instances directly; use Specifi
- expected a SpecifierSet
- Invalid version: {version!r}
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/51ba88e4366f8910.
Report an issue: GitHub.