{"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/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_internal/resolution/resolvelib/factory.py#L535-L571","documentation":"InstallationError from check_invalid_constraint_type when a constraint entry has extras, e.g. 'package[extra]'. Constraints narrow the version of a single project; extras are an install-time selection and cannot be expressed as a constraint, so the resolver rejects the entry (after a deprecation warning).","triggerScenarios":"A constraints file ('-c') contains 'package[test]' or 'package[extra1,extra2]'. req.extras is non-empty in check_invalid_constraint_type, the problem string is set, and collect_root_requirements raises.","commonSituations":"Lockfile tool emitting extras into a constraints file; reusing a dev-requirements file as constraints; combining extras with version pins in the same file.","solutions":["Strip the '[...]' extras from every line in the constraints file, leaving just 'package<specifier>'.","Put extras on the install side: in requirements.txt use 'package[test]', in constraints.txt use 'package'.","Re-generate constraints from your lockfile with extras excluded.","Re-run pip to confirm no constraint carries extras."],"exampleFix":"# before — constraints.txt\nrequests[socks]==2.31.0\n\n# after\nrequests==2.31.0   # extras belong in requirements.txt, not constraints.txt","handlingStrategy":"validation","validationCode":"def constraints_have_no_extras(path: str) -> bool:\n    import re\n    bad = [l.strip() for l in open(path) if re.search(r'\\[[^\\]]+\\]', l)]\n    if bad:\n        print(f'extras in constraints: {bad}'); return False\n    return True","typeGuard":"def is_constraint_without_extras(line: str) -> bool:\n    import re\n    return not re.search(r'^[^\\s#-]\\S*\\[[^\\]]+\\]', line.strip())","tryCatchPattern":"if not constraints_have_no_extras('constraints.txt'):\n    print('strip extras from constraints lines')\nelse:\n    run_pip(['install', '-c', 'constraints.txt', 'pkg'])","preventionTips":["Keep extras only on install-side requirements.","Lint constraints files for '[...]' tokens.","Document the constraints vs requirements split in your repo README."],"tags":["constraints","extras","resolver","config"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}