{"record":{"id":"835b8ee9c30281c1","repo":"pypa/pip","slug":"invalid-requirement-req-as-string-r-exc","errorCode":null,"errorMessage":"Invalid requirement: {req_as_string!r}: {exc}","messagePattern":"Invalid requirement: (.+?): (.+?)","errorType":"validation","errorClass":"InstallationError","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/req/constructors.py","lineNumber":405,"sourceCode":"        return f\"{text} (from {line_source})\"\n\n    def _parse_req_string(req_as_string: str) -> Requirement:\n        try:\n            return get_requirement(req_as_string)\n        except InvalidRequirement as exc:\n            if os.path.sep in req_as_string:\n                add_msg = \"It looks like a path.\"\n                add_msg += deduce_helpful_msg(req_as_string)\n            elif \"=\" in req_as_string and not any(\n                op in req_as_string for op in operators\n            ):\n                add_msg = \"= is not a valid operator. Did you mean == ?\"\n            else:\n                add_msg = \"\"\n            msg = with_source(f\"Invalid requirement: {req_as_string!r}: {exc}\")\n            if add_msg:\n                msg += f\"\\nHint: {add_msg}\"\n            raise InstallationError(msg)\n\n    if req_as_string is not None:\n        req: Requirement | None = _parse_req_string(req_as_string)\n    else:\n        req = None\n\n    return RequirementParts(req, link, markers, extras)\n\n\ndef install_req_from_line(\n    name: str,\n    comes_from: str | InstallRequirement | None = None,\n    *,\n    isolated: bool = False,\n    hash_options: dict[str, list[str]] | None = None,\n    constraint: bool = False,\n    line_source: str | None = None,\n    user_supplied: bool = False,","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/req/constructors.py#L387-L423","documentation":"The general-purpose requirement string parser (_parse_req_string inside parse_req_from_line) could not build a Requirement object from the resolved requirement string. This is the most common 'Invalid requirement' error, enhanced with contextual hints: it detects when the string looks like a path or uses '=' instead of '=='.","triggerScenarios":"Running 'pip install foo=1.0' (single equals). Passing a bare path that doesn't resolve to an installable. Any PEP 508 syntax error in a requirement string from the command line or a requirements file line.","commonSituations":"Using '=' instead of '==' for version pinning. Misspelled package names. Requirement strings with stray characters. Requirements files with lines that were corrupted by environment variable expansion or line-joining.","solutions":["Use '==' for exact version pins: 'foo==1.0' not 'foo=1.0'","Read the Hint in the error message — it specifically detects path-like strings and single-equals mistakes","Validate the string with packaging.requirements.Requirement() in a REPL to get a precise error","Check for invisible characters or encoding issues in requirements files"],"exampleFix":"# before\npip install requests=2.28.0\n\n# after\npip install requests==2.28.0","handlingStrategy":"validation","validationCode":"from pip._vendor.packaging.requirements import Requirement, InvalidRequirement\n\ndef validate_requirement_string(req_str: str) -> bool:\n    try:\n        Requirement(req_str)\n        return True\n    except InvalidRequirement:\n        return False\n\nfor line in requirements_lines:\n    if not validate_requirement_string(line):\n        print(f\"Invalid requirement: {line!r}\")","typeGuard":"from pip._vendor.packaging.requirements import Requirement, InvalidRequirement\n\ndef is_valid_requirement(req_str: str) -> bool:\n    \"\"\"Type guard: True if req_str parses as a valid PEP 508 requirement.\"\"\"\n    try:\n        Requirement(req_str)\n        return True\n    except InvalidRequirement:\n        return False","tryCatchPattern":"from pip._internal.exceptions import InstallationError\n\ntry:\n    parts = parse_req_from_line(name, line_source)\nexcept InstallationError as e:\n    msg = str(e)\n    if \"Did you mean ==\" in msg:\n        # auto-fix single-equals\n        fixed = name.replace(\"=\", \"==\", 1)\n        parts = parse_req_from_line(fixed, line_source)\n    else:\n        raise","preventionTips":["Use == for version pinning, never a single =","Validate requirement strings with packaging.requirements.Requirement() before passing to pip","Run a pre-commit hook that checks requirements files for single-equals typos"],"tags":["pip","pep508","parsing","requirements","version-specifier"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}