pypa/pip · error · InstallationError
Constraints cannot have extras
Error message
Constraints cannot have extras
What it means
check_invalid_constraint_type (req_install.py:815-816) and collect_root_requirements (factory.py:551-553) reject constraint entries that carry extras (e.g. pkg[extra]==1.0). Extras select optional dependencies and are not a version constraint, so the new resolver forbids extras in -c constraint files.
Solutions
- Remove the extras bracket from the constraint line: pkg==1.0.
- Put pkg[extra] (with extras) in the main requirements file and keep only pkg==1.0 in the constraints file.
Example fix
# before (constraints.txt) pkg[test]==1.0 # after # constraints.txt: pkg==1.0 # requirements.txt: pkg[test]
Defensive patterns
Strategy: validation
Validate before calling
# Validate a constraints file has no extras in package specs.
import re
for line in open("constraints.txt"):
s = line.strip()
if not s or s.startswith("#"):
continue
if re.search(r"[A-Za-z0-9._-]+\[[^\]]+\]", s):
print(f"Extras not allowed in constraints: {s}") Prevention
- Keep extras in the requirements file, not the constraints file.
- Constraint lines should be bare 'name<specifier>'.
- Add a CI lint step rejecting 'name[...]' in constraints files.
When it happens
Trigger: A constraints file (-c) contains a line like `pkg[extra]==1.0`.
Common situations: Copy-pasting a requirements line with extras into a constraints file; expecting constraints to also enable optional deps.
Related errors
- Could not open file
- Could not satisfy constraints for
- Editable requirements are not allowed as constraints
- Expected extra name after comma
- has no such extra feature %r
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/a7009b949f806d6c.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/resolution/resolvelib/factory.py:553
else:
# require the base from the link
yield self.make_requirement_from_candidate(cand)
if ireq.extras:
# require the extras on top of the base candidate
yield self.make_requirement_from_candidate(
self._make_extras_candidate(cand, frozenset(ireq.extras))
)
def collect_root_requirements(
self, root_ireqs: list[InstallRequirement]
) -> CollectedRootRequirements:
collected = CollectedRootRequirements([], {}, {})
for i, ireq in enumerate(root_ireqs):
if ireq.constraint:
# Ensure we only accept valid constraints
problem = check_invalid_constraint_type(ireq)
if problem:
raise InstallationError(problem)
if not ireq.match_markers():
continue
assert ireq.name, "Constraint must be named"
name = canonicalize_name(ireq.name)
if name in collected.constraints:
collected.constraints[name] &= ireq
else:
collected.constraints[name] = Constraint.from_ireq(ireq)
else:
reqs = list(
self._make_requirements_from_install_req(
ireq,
requested_extras=(),
)
)
if not reqs:
continue
template = reqs[0]View on GitHub (pinned to f399c37189)