pypa/pip · error · ValueError
Cannot combine SpecifierSets with True and False prerelease…
Error message
Cannot combine SpecifierSets with True and False prerelease overrides.
What it means
Raised as ValueError by SpecifierSet.__and__ (specifiers.py:996) when intersecting two SpecifierSets whose explicit prerelease overrides conflict: one has prereleases=True and the other prereleases=False (both non-None and unequal). The combination logic at lines 991-994 accepts a None on either side or matching values, but explicitly forbids the True-vs-False clash because there is no defensible combined policy.
Solutions
- Reconcile the prerelease policy before combining: pass the same prereleases value (or None) to both SpecifierSets, or leave both unset to let autodetect decide.
- If you must merge, strip the override by reconstructing one side as SpecifierSet(str(other)) (str drops prereleases) before the & operation.
- Decide a single project-wide prerelease policy and apply it at the top level rather than per-SpecifierSet.
- Wrap the & in try/except ValueError and surface a clear 'conflicting prerelease policy' error naming both sources.
Example fix
# before
a = SpecifierSet('>=1.0', prereleases=True)
b = SpecifierSet('<2.0', prereleases=False)
combined = a & b # ValueError
# after - drop the conflicting override, apply one policy
b = SpecifierSet(str(b)) # prereleases=None
combined = a & b # ok; combined honors prereleases=True Defensive patterns
Strategy: validation
Validate before calling
from packaging.specifiers import SpecifierSet
def combine(a: SpecifierSet, b: SpecifierSet) -> SpecifierSet:
# Drop conflicting prerelease overrides by normalizing to string form.
if a._prereleases is not None and b._prereleases is not None and a._prereleases != b._prereleases:
b = SpecifierSet(str(b)) # prereleases=None
return a & b Try / catch
try:
combined = a & b
except ValueError:
# conflicting prerelease policy; pick one explicit policy
combined = SpecifierSet(str(a) + ',' + str(b), prereleases=True) Prevention
- Establish one prerelease policy per merge operation and apply it once.
- When building SpecifierSets from layered config, leave prereleases unset unless explicitly needed.
- Reconstruct one side from str() to drop its override before combining.
When it happens
Trigger: SpecifierSet('>=1.0', prereleases=True) & SpecifierSet('<2.0', prereleases=False); building a combined requirement programmatically where one source forces prereleases on and another forces them off; intersecting a tool's resolver settings (prereleases enabled) with a project policy (prereleases disabled).
Common situations: A resolver/aggregator merging constraints from multiple sources (e.g. user flag --pre vs. project requires_python style guards); pinning tools that let callers set prerelease policy per-constraint then combine them; config layers where one layer sets prereleases=True globally and another layer overrides a subset to False.
Related errors
- Cannot combine VersionRange operands with different…
- Cannot restore Specifier from
- Cannot restore SpecifierSet from
- expected a SpecifierSet
- Invalid specifier
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/fde6d53ca2d96972.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/packaging/specifiers.py:996
<SpecifierSet('!=1.0.1,!=2.0.1,<=2.0.0,>=1.0.0')>
"""
if isinstance(other, str):
other = SpecifierSet(other)
elif not isinstance(other, SpecifierSet):
return NotImplemented
specifier = SpecifierSet()
specifier._specs = self._specs + other._specs
specifier._canonicalized = len(specifier._specs) <= 1
specifier._has_arbitrary = self._has_arbitrary or other._has_arbitrary
# Combine prerelease settings: use common or non-None value
if self._prereleases is None or self._prereleases == other._prereleases:
specifier._prereleases = other._prereleases
elif other._prereleases is None:
specifier._prereleases = self._prereleases
else:
raise ValueError(
"Cannot combine SpecifierSets with True and False prerelease overrides."
)
return specifier
def __eq__(self, other: object) -> bool:
"""Whether or not the two SpecifierSet-like objects are equal.
:param other: The other object to check against.
The value of :attr:`prereleases` is ignored.
>>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.1")
True
>>> (SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False) ==
... SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True))
True
>>> SpecifierSet(">=1.0.0,!=1.0.1") == ">=1.0.0,!=1.0.1"View on GitHub (pinned to f399c37189)