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

  1. Validate/percent-encode URLs client-side before sending requests
  2. Use urllib.parse.quote on path components when constructing URLs
  3. 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

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


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/a9f5cf29204f4788. Report an issue: GitHub.