{"id":"15d656510d98293f","repo":"pypa/pip","slug":"invalid-requirement-req-string-r-exc","errorCode":null,"errorMessage":"Invalid requirement: {req_string!r}: {exc}","messagePattern":"Invalid requirement: (.+?): (.+?)","errorType":"exception","errorClass":"InstallationError","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/req/constructors.py","lineNumber":457,"sourceCode":"        isolated=isolated,\n        hash_options=hash_options,\n        config_settings=config_settings,\n        constraint=constraint,\n        extras=parts.extras,\n        user_supplied=user_supplied,\n    )\n\n\ndef install_req_from_req_string(\n    req_string: str,\n    comes_from: InstallRequirement | None = None,\n    isolated: bool = False,\n    user_supplied: bool = False,\n) -> InstallRequirement:\n    try:\n        req = get_requirement(req_string)\n    except InvalidRequirement as exc:\n        raise InstallationError(f\"Invalid requirement: {req_string!r}: {exc}\")\n\n    domains_not_allowed = [\n        PyPI.file_storage_domain,\n        TestPyPI.file_storage_domain,\n    ]\n    if (\n        req.url\n        and comes_from\n        and comes_from.link\n        and comes_from.link.netloc in domains_not_allowed\n    ):\n        # Explicitly disallow pypi packages that depend on external urls\n        raise InstallationError(\n            \"Packages installed from PyPI cannot depend on packages \"\n            \"which are not also hosted on PyPI.\\n\"\n            f\"{comes_from.name} depends on {req} \"\n        )\n","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_internal/req/constructors.py#L439-L475","documentation":"Raised by install_req_from_req_string() when a raw requirement string fails PEP 508 parsing via get_requirement (constructors.py:456). This is the simplest of the parse paths — there is no path/URL/marker pre-processing, so any syntactically invalid requirement specifier triggers it. Used internally for requirements constructed from already-separated strings.","triggerScenarios":"Programmatic callers passing a malformed req_string to install_req_from_req_string. Strings with bad operators, unparseable names, or invalid extras syntax like `package[ ]`.","commonSituations":"Internal pip code paths constructing requirements from dependency metadata. Third-party tools calling install_req_from_req_string with unvalidated user input. Malformed metadata in a wheel or sdist.","solutions":["Sanitize/validate the requirement string with packaging.requirements.Requirement before passing it in.","Correct the operator/name/extras syntax to conform to PEP 508.","If the string originates from a third-party source, report the malformed metadata upstream."],"exampleFix":"# before\ninstall_req_from_req_string(\"package =1.0\")\n# after\ninstall_req_from_req_string(\"package==1.0\")","handlingStrategy":"validation","validationCode":"from packaging.requirements import Requirement, InvalidRequirement\n\ndef safe_req_string(s: str) -> Requirement:\n    try:\n        return Requirement(s)\n    except InvalidRequirement as e:\n        raise ValueError(f\"Invalid requirement string {s!r}: {e}\") from e","typeGuard":"from packaging.requirements import Requirement, InvalidRequirement\n\ndef is_valid_req_string(s: str) -> bool:\n    try:\n        Requirement(s)\n        return True\n    except InvalidRequirement:\n        return False","tryCatchPattern":"null","preventionTips":["Always parse requirement strings with packaging.requirements.Requirement before handing them to pip internals.","Sanitize user-supplied input that becomes requirement strings.","Reject single-= operators early."],"tags":["requirements","pep508","validation","packaging"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}