sgl-project/sglang · error · ValueError
Invalid media URL: {current_url!r}
Error message
Invalid media URL: {current_url!r} What it means
Before each fetch (and after each redirect hop), download_remote_media re-prepares the URL via requests.Request(...).prepare(); if preparation yields None the URL is unparseable by the actual HTTP client and is rejected. This validates the exact normalized URL string requests/urllib3 will send, avoiding parser-disagreement tricks (backslashes, userinfo).
Source
Thrown at python/sglang/srt/utils/common.py:1611
a connection is made. The response is streamed to enforce both the total
request deadline and the configured byte limit without first buffering an
attacker-controlled body in memory.
"""
if timeout <= 0:
raise ValueError("media URL timeout must be positive")
session = get_mm_http_session()
deadline = time.monotonic() + timeout
current_url = url
for redirect_count in range(_MAX_MEDIA_URL_REDIRECTS + 1):
# Validate the same normalized URL representation that requests sends
# to urllib3. This avoids parser disagreements around backslashes and
# userinfo separators.
prepared_url = requests.Request("GET", current_url).prepare().url
if prepared_url is None:
raise ValueError(f"Invalid media URL: {current_url!r}")
_assert_media_url_allowed(prepared_url)
remaining = deadline - time.monotonic()
if remaining <= 0:
raise requests.exceptions.Timeout(
f"Timed out while downloading media URL: {url}"
)
with session.get(
prepared_url,
allow_redirects=False,
stream=True,
timeout=remaining,
) as response:
location = response.headers.get("Location")
if response.status_code in _MEDIA_URL_REDIRECT_STATUS_CODES and location:
if redirect_count == _MAX_MEDIA_URL_REDIRECTS:
raise requests.exceptions.TooManyRedirects(View on GitHub (pinned to 0132848349)
Solutions
- Validate/percent-encode URLs client-side before sending requests
- Use urllib.parse.quote on path components when constructing URLs
- Catch ValueError around the media fetch and return a 400 to the client instead of crashing the worker
Example fix
# before
url = 'https://example.com/a b.png' # space -> prepare() may fail
# after
from urllib.parse import quote
data = download_remote_media('https://example.com/' + quote('a b.png'), timeout=30) Defensive patterns
Strategy: try-catch
Validate before calling
from urllib.parse import quote, urlparse
u = urlparse(candidate)
if u.scheme not in ('http', 'https') or not u.hostname: reject()
url = u._replace(path=quote(u.path, safe='/:%')).geturl() Try / catch
try:
data = download_remote_media(url, timeout=30)
except ValueError as e:
if 'Invalid media URL' in str(e):
return HTTPException(400, f'unparseable media URL: {url!r}')
raise Prevention
- Percent-encode user-supplied URL components client-side
- Treat unparseable URLs as client errors (400), not worker crashes
When it happens
Trigger: Passing malformed URLs that urlparse tolerates but requests cannot prepare (control characters, invalid percent-encoding, schemes like 'http:////x'); also reached on a redirect Location header containing such a URL.
Common situations: User-supplied image/audio URLs with unencoded spaces or control chars; malicious or broken redirect targets; double-encoded strings from JSON payloads.
Related errors
- Invalid media URL: {url!r}
- Media URL domain is not allowed. Allowed domains: {sorted(_a
- allowed media domains must be strings
- allowed media domains cannot be empty
- Invalid allowed media domain {domain!r}: provide a hostname
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/a9f5cf29204f4788.
Report an issue: GitHub.