{"record":{"id":"a7009b949f806d6c","repo":"pypa/pip","slug":"constraints-cannot-have-extras","errorCode":null,"errorMessage":"Constraints cannot have extras","messagePattern":"Constraints cannot have extras","errorType":"exception","errorClass":"InstallationError","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/resolution/resolvelib/factory.py","lineNumber":553,"sourceCode":"            else:\n                # require the base from the link\n                yield self.make_requirement_from_candidate(cand)\n                if ireq.extras:\n                    # require the extras on top of the base candidate\n                    yield self.make_requirement_from_candidate(\n                        self._make_extras_candidate(cand, frozenset(ireq.extras))\n                    )\n\n    def collect_root_requirements(\n        self, root_ireqs: list[InstallRequirement]\n    ) -> CollectedRootRequirements:\n        collected = CollectedRootRequirements([], {}, {})\n        for i, ireq in enumerate(root_ireqs):\n            if ireq.constraint:\n                # Ensure we only accept valid constraints\n                problem = check_invalid_constraint_type(ireq)\n                if problem:\n                    raise InstallationError(problem)\n                if not ireq.match_markers():\n                    continue\n                assert ireq.name, \"Constraint must be named\"\n                name = canonicalize_name(ireq.name)\n                if name in collected.constraints:\n                    collected.constraints[name] &= ireq\n                else:\n                    collected.constraints[name] = Constraint.from_ireq(ireq)\n            else:\n                reqs = list(\n                    self._make_requirements_from_install_req(\n                        ireq,\n                        requested_extras=(),\n                    )\n                )\n                if not reqs:\n                    continue\n                template = reqs[0]","sourceCodeStart":535,"sourceCodeEnd":571,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/resolution/resolvelib/factory.py#L535-L571","documentation":"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.","triggerScenarios":"A constraints file (-c) contains a line like `pkg[extra]==1.0`.","commonSituations":"Copy-pasting a requirements line with extras into a constraints file; expecting constraints to also enable optional deps.","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."],"exampleFix":"# before (constraints.txt)\npkg[test]==1.0\n# after\n# constraints.txt:\npkg==1.0\n# requirements.txt:\npkg[test]","handlingStrategy":"validation","validationCode":"# Validate a constraints file has no extras in package specs.\nimport re\nfor line in open(\"constraints.txt\"):\n    s = line.strip()\n    if not s or s.startswith(\"#\"):\n        continue\n    if re.search(r\"[A-Za-z0-9._-]+\\[[^\\]]+\\]\", s):\n        print(f\"Extras not allowed in constraints: {s}\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["constraints","extras"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}