pypa/pip · error · InstallationError
Invalid requirement: {req_as_string!r}: {exc}
Error message
Invalid requirement: {req_as_string!r}: {exc} What it means
Raised by the inner _parse_req_string() in parse_req_from_line() when the requirement string itself (after path/URL/marker handling) cannot be parsed by get_requirement as a valid PEP 508 requirement. The error at constructors.py:405 includes a smart hint: it detects path-like strings, single-`=` mistakes, etc.
Source
Thrown at src/pip/_internal/req/constructors.py:405
return f"{text} (from {line_source})"
def _parse_req_string(req_as_string: str) -> Requirement:
try:
return get_requirement(req_as_string)
except InvalidRequirement as exc:
if os.path.sep in req_as_string:
add_msg = "It looks like a path."
add_msg += deduce_helpful_msg(req_as_string)
elif "=" in req_as_string and not any(
op in req_as_string for op in operators
):
add_msg = "= is not a valid operator. Did you mean == ?"
else:
add_msg = ""
msg = with_source(f"Invalid requirement: {req_as_string!r}: {exc}")
if add_msg:
msg += f"\nHint: {add_msg}"
raise InstallationError(msg)
if req_as_string is not None:
req: Requirement | None = _parse_req_string(req_as_string)
else:
req = None
return RequirementParts(req, link, markers, extras)
def install_req_from_line(
name: str,
comes_from: str | InstallRequirement | None = None,
*,
isolated: bool = False,
hash_options: dict[str, list[str]] | None = None,
constraint: bool = False,
line_source: str | None = None,
user_supplied: bool = False,View on GitHub (pinned to d7d0d0a394)
Solutions
- Follow the Hint in the error message: if it suggests `==`, replace single `=` with `==`.
- If the hint says the argument looks like a requirements file, re-run with `-r <file>`.
- Validate the line standalone: `python -c "from packaging.requirements import Requirement; Requirement('YOUR_LINE')"`.
- Strip invisible characters and normalize quotes if copy-pasted from a rich-text source.
Example fix
# before package =1.0 # after package==1.0
Defensive patterns
Strategy: validation
Validate before calling
from packaging.requirements import Requirement, InvalidRequirement
def validate_req_line(line: str) -> Requirement:
# strip markers/path handling is pip's job; here we sanity-check the core specifier
core = line.split(";", 1)[0].strip()
try:
return Requirement(core)
except InvalidRequirement as e:
raise ValueError(f"Invalid requirement line {line!r}: {e}") from e Type guard
from packaging.requirements import Requirement, InvalidRequirement
def is_valid_req_line(line: str) -> bool:
try:
Requirement(line.split(";", 1)[0].strip())
return True
except InvalidRequirement:
return False Try / catch
null
Prevention
- Use == instead of = for version pinning.
- If pip hints the arg looks like a requirements file, pass it with -r.
- Lint requirements files in CI by parsing every line with packaging.
When it happens
Trigger: A requirements line with bad syntax: `package =1.0` (single equals), an unparseable name, a version specifier with stray characters, or a path-like token that is neither a valid file nor a valid requirement. The hint logic at constructors.py:393-404 appends advice based on heuristics.
Common situations: Using `=` instead of `==`. Forgetting the package name and writing just a version. Stray whitespace or non-ASCII characters. A requirements file accidentally passed without -r.
Related errors
- Invalid requirement: {req_string!r}: {exc}
- Invalid requirement: {name!r}: {exc}
- Invalid requirement: {name.strip()!r}: {exc}
- invalid version: %s
- invalid constraint: %s
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/835b8ee9c30281c1.json.
Report an issue: GitHub.