pypa/pip · error · SyntaxError
comma expected in extras: %s
Error message
comma expected in extras: %s
What it means
Raised by distlib's `parse_requirement` while parsing a multi-value extras list: after consuming one extra, the next character must be `,` to separate further extras. If it isn't (e.g. a stray letter or punctuation), the parser raises `SyntaxError: comma expected in extras`.
Source
Thrown at src/pip/_vendor/distlib/util.py:174
remaining = remaining[m.end():]
extras = mark_expr = versions = uri = None
if remaining and remaining[0] == '[':
i = remaining.find(']', 1)
if i < 0:
raise SyntaxError('unterminated extra: %s' % remaining)
s = remaining[1:i]
remaining = remaining[i + 1:].lstrip()
extras = []
while s:
m = IDENTIFIER.match(s)
if not m:
raise SyntaxError('malformed extra: %s' % s)
extras.append(m.groups()[0])
s = s[m.end():]
if not s:
break
if s[0] != ',':
raise SyntaxError('comma expected in extras: %s' % s)
s = s[1:].lstrip()
if not extras:
extras = None
if remaining:
if remaining[0] == '@':
# it's a URI
remaining = remaining[1:].lstrip()
m = NON_SPACE.match(remaining)
if not m:
raise SyntaxError('invalid URI: %s' % remaining)
uri = m.groups()[0]
t = urlparse(uri)
# there are issues with Python and URL parsing, so this test
# is a bit crude. See bpo-20271, bpo-23505. Python doesn't
# always parse invalid URLs correctly - it should raise
# exceptions for malformed URLs
if not (t.scheme and t.netloc):
raise SyntaxError('Invalid URL: %s' % uri)View on GitHub (pinned to d7d0d0a394)
Solutions
- Separate multiple extras with commas: `pkg[extra1,extra2]`.
- Remove whitespace/punctuation that isn't a comma between extras.
- Validate with `packaging.requirements.Requirement(...)`.
Example fix
# before requests[security socks] # after requests[security,socks]
Defensive patterns
Strategy: validation
Validate before calling
from packaging.requirements import Requirement, InvalidRequirement
def validate_requirement(line: str) -> None:
try:
Requirement(line)
except InvalidRequirement as e:
raise ValueError(f"Bad requirement: {e}") from e Type guard
import re
def extras_use_commas(line: str) -> bool:
m = re.search(r"\[([^\]]*)\]", line)
if not m:
return True
inner = m.group(1).strip()
if not inner:
return True
# multiple extras must be comma-separated
parts = inner.split(",")
return all(re.match(r"^[A-Za-z_][\\w.-]*$", p.strip()) for p in parts) Try / catch
null
Prevention
- Separate multiple extras with commas only: `pkg[a,b,c]`.
- Avoid spaces/semicolons between extras.
- Validate with `packaging.requirements.Requirement`.
When it happens
Trigger: Parsing a requirement like `pkg[extra1 extra2]` (space instead of comma) or `pkg[extra1;extra2]`. Triggered when the extras list contains more than one entry without comma separators.
Common situations: Using spaces, semicolons, or other delimiters instead of commas between extras; typos; copy-paste from sources that used a different separator.
Related errors
- unterminated extra: %s
- malformed extra: %s
- error in string literal: %s
- unterminated string: %s
- unterminated parenthesis: %s
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/1f0fcbc721888f2e.json.
Report an issue: GitHub.