pypa/pip · error · SyntaxError
invalid requirement: %s
Error message
invalid requirement: %s
What it means
Raised by parse_requirement() when, after parsing the name, extras, and version/URL, there is leftover text whose first character is not ';' (the marker separator). This means the requirement has trailing content that is neither a valid URL, version clause, nor a marker, so it is rejected as an invalid requirement (SyntaxError).
Source
Thrown at src/pip/_vendor/distlib/util.py:253
remaining = remaining[i + 1:].lstrip()
# As a special diversion from PEP 508, allow a version number
# a.b.c in parentheses as a synonym for ~= a.b.c (because this
# is allowed in earlier PEPs)
if COMPARE_OP.match(s):
versions, _ = get_versions(s)
else:
m = VERSION_IDENTIFIER.match(s)
if not m:
raise SyntaxError('invalid constraint: %s' % s)
v = m.groups()[0]
s = s[m.end():].lstrip()
if s:
raise SyntaxError('invalid constraint: %s' % s)
versions = [('~=', v)]
if remaining:
if remaining[0] != ';':
raise SyntaxError('invalid requirement: %s' % remaining)
remaining = remaining[1:].lstrip()
mark_expr, remaining = parse_marker(remaining)
if remaining and remaining[0] != '#':
raise SyntaxError('unexpected trailing data: %s' % remaining)
if not versions:
rs = distname
else:
rs = '%s %s' % (distname, ', '.join(['%s %s' % con for con in versions]))
return Container(name=distname, extras=extras, constraints=versions, marker=mark_expr, url=uri, requirement=rs)
def get_resources_dests(resources_root, rules):
"""Find destinations for resources files"""
def get_rel_path(root, path):View on GitHub (pinned to d7d0d0a394)
Solutions
- Remove the trailing junk shown after 'invalid requirement:'.
- If the trailing text is an environment marker, prefix it with '; ': 'pkg >= 1.0 ; python_version >= "3.8"'.
- If it is a comment, prefix it with '#'.
Example fix
// before
parse_requirement('requests >= 2.31.0 security')
// after
parse_requirement('requests >= 2.31.0') Defensive patterns
Strategy: try-catch
Try / catch
from distlib.util import parse_requirement
try:
spec = parse_requirement(raw)
except SyntaxError as e:
if 'invalid requirement' in str(e):
# the whole string is malformed; surface to user / skip line
continue
raise Prevention
- Keep one requirement per line in requirements.txt.
- Prefix environment markers with '; ' and comments with '#'.
- Validate requirement files line-by-line in a try/except loop.
When it happens
Trigger: parse_requirement('pkg extra'), parse_requirement('pkg >= 1.0 garbage'), parse_requirement('pkg[extra] something'), or any requirement with unparseable trailing tokens that do not start with ';'.
Common situations: Typos in requirements.txt (e.g. a stray word), comments appended without a '#', or concatenation of a requirement with extra metadata without a separator.
Related errors
- invalid version: %s
- invalid constraint: %s
- unexpected trailing data: %s
- Invalid requirement: {req_as_string!r}: {exc}
- Invalid requirement: {req_string!r}: {exc}
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/99ed8217502d0423.json.
Report an issue: GitHub.