pypa/pip · error · ParserSyntaxError
Expected whitespace after URL
Error message
Expected whitespace after URL
What it means
Raised as a ParserSyntaxError (surfacing as InvalidRequirement) at line 152 when, after reading the URL in a direct-URL requirement, the next token is neither END nor whitespace (WS). The grammar requires whitespace separating the URL from any following marker clause (line 152); only end-of-input is exempt (line 149-150).
Solutions
- Insert a space between the URL and the semicolon: 'pkg @ https://x/y.tar.gz ; python_version >= "3.0"'.
- When concatenating fragments, always join URL and marker with ' ' rather than '' or ';'.
- Round-trip the constructed string through Requirement(...).str() to normalize spacing.
Example fix
// before
Requirement('pkg @ https://x/y.tar.gz;python_version >= "3.0"')
// after
Requirement('pkg @ https://x/y.tar.gz ; python_version >= "3.0"') Defensive patterns
Strategy: validation
Validate before calling
import re
def normalized_url_req(name, url, marker=None):
parts = [f'{name} @ {url}']
if marker:
parts.append(f'; {marker}')
return ' '.join(parts) Try / catch
from packaging.requirements import Requirement, InvalidRequirement
try:
req = Requirement(raw)
except InvalidRequirement as e:
if 'whitespace after URL' in str(e):
raw = raw.replace(';', ' ;', 1) # attempt space insertion
req = Requirement(raw)
raise Prevention
- Always separate the URL from the marker semicolon with whitespace.
- Build URL requirements from structured parts rather than string concatenation.
When it happens
Trigger: A direct-URL requirement with a marker clause attached directly to the URL with no space, e.g. 'pkg @ https://x/y.tar.gz;python_version >= "3.0"'. The ';' (or other token) follows the URL immediately with no WS, so tokenizer.expect("WS", ...) fails.
Common situations: Programmatically building 'name @ ' + url + ';' + marker without inserting a space; minified/compressed requirement strings; copy-paste losing the separating space.
Related errors
- Expected URL after @
- Expected end of dependency specifier
- Expected extra name after comma
- Expected whitespace after 'not'
- Expected end of marker expression
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/51729fa729048d1a.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/packaging/_parser.py:152
"""
requirement_details = AT URL (WS requirement_marker?)?
| specifier WS? (requirement_marker)?
"""
specifier = ""
url = ""
marker = None
if tokenizer.check("AT"):
tokenizer.read()
tokenizer.consume("WS")
url_start = tokenizer.position
url = tokenizer.expect("URL", expected="URL after @").text
if tokenizer.check("END", peek=True):
return (url, specifier, marker)
tokenizer.expect("WS", expected="whitespace after URL")
# The input might end after whitespace.
if tokenizer.check("END", peek=True):
return (url, specifier, marker)
marker = _parse_requirement_marker(
tokenizer,
span_start=url_start,
expected="semicolon (after URL and whitespace)",
)
else:
specifier_start = tokenizer.position
specifier = _parse_specifier(tokenizer)
tokenizer.consume("WS")
if tokenizer.check("END", peek=True):
return (url, specifier, marker)
View on GitHub (pinned to f399c37189)