pypa/pip · error · InstallationError
Invalid requirement
Error message
Invalid requirement: {req_as_string!r}: {exc} What it means
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 '=='.
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
Example fix
# before pip install requests=2.28.0 # after pip install requests==2.28.0
Defensive patterns
Strategy: validation
Validate before calling
from pip._vendor.packaging.requirements import Requirement, InvalidRequirement
def validate_requirement_string(req_str: str) -> bool:
try:
Requirement(req_str)
return True
except InvalidRequirement:
return False
for line in requirements_lines:
if not validate_requirement_string(line):
print(f"Invalid requirement: {line!r}") Type guard
from pip._vendor.packaging.requirements import Requirement, InvalidRequirement
def is_valid_requirement(req_str: str) -> bool:
"""Type guard: True if req_str parses as a valid PEP 508 requirement."""
try:
Requirement(req_str)
return True
except InvalidRequirement:
return False Try / catch
from pip._internal.exceptions import InstallationError
try:
parts = parse_req_from_line(name, line_source)
except InstallationError as e:
msg = str(e)
if "Did you mean ==" in msg:
# auto-fix single-equals
fixed = name.replace("=", "==", 1)
parts = parse_req_from_line(fixed, line_source)
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Invalid requirement
- Invalid requirement
- invalid requirement
- unexpected trailing data
- Configuration file could not be loaded.\n
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/835b8ee9c30281c1.
Report an issue: GitHub.
Appendix: 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 f399c37189)