sgl-project/sglang · error · ValueError

data URI must use ;base64 encoding

Error message

data URI must use ;base64 encoding

What it means

The data-URI header parsed from a 'data:' material URI must contain the ';base64' marker, because the loader only decodes base64 payloads (not percent-encoded or plain-text data URIs). Without it the payload encoding is ambiguous and decoding would corrupt the material.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/material_io.py:102

                    shutil.rmtree(str(path), ignore_errors=True)
        if not registry:
            batch.extra.pop(MINIMAX_H3_TEMP_DIRS_EXTRA_KEY, None)
    if owners is None or "material" in selected:
        batch.extra.pop(MINIMAX_H3_MATERIAL_CACHE_EXTRA_KEY, None)
        batch.extra.pop(MINIMAX_H3_MATERIAL_PROBE_EXTRA_KEY, None)


def _base64_uri_payload_start(uri: str) -> tuple[int, str | None]:
    media_type = None
    if uri.startswith("data:"):
        separator = uri.find(",")
        if separator < 0:
            raise ValueError("data URI must contain a comma separator")
        if separator > MINIMAX_H3_BASE64_HEADER_MAX_CHARS:
            raise ValueError("data URI header is too large")
        header = uri[:separator]
        if ";base64" not in header:
            raise ValueError("data URI must use ;base64 encoding")
        media_type = header[5:].split(";", 1)[0].lower() or None
        payload_start = separator + 1
    elif uri.startswith("base64://"):
        payload_start = len("base64://")
        separator = uri.find(",", payload_start)
        if separator >= 0:
            if separator - payload_start > MINIMAX_H3_BASE64_HEADER_MAX_CHARS:
                raise ValueError("base64 URI header is too large")
            header = uri[payload_start:separator]
            media_type = header.split(";", 1)[0].lower() or None
            payload_start = separator + 1
    else:  # pragma: no cover - guarded by the caller
        raise ValueError("not a base64 material URI")
    return payload_start, media_type


def _iter_base64_payload_bytes(uri: str, payload_start: int):
    """Yield validated, unquoted base64 bytes without copying the payload."""

View on GitHub (pinned to 0132848349)

Solutions

  1. Emit ';base64' in the header: 'data:image/png;base64,<payload>'
  2. If the source is raw bytes, base64-encode them before building the URI
  3. Pre-validate that ';base64' appears before the first comma in the URI

Example fix

// before
uri = f"data:image/png,{quote(png_bytes)}"
// after
uri = "data:image/png;base64," + base64.b64encode(png_bytes).decode('ascii')
Defensive patterns

Strategy: validation

Validate before calling

if uri.startswith('data:'):
    header = uri.split(',', 1)[0]
    assert ';base64' in header, 'data URI must declare ;base64'

Type guard

def is_base64_data_uri(uri: str) -> bool:
    return uri.startswith('data:') and ';base64' in uri.split(',', 1)[0]

Prevention

When it happens

Trigger: Passing URIs like 'data:image/png,<percent-encoded-bytes>' or 'data:text/plain,hello' to _stream_base64_material.

Common situations: Using HTML-style inline data URIs (which permit other encodings), LLM-generated URIs omitting the ;base64 parameter, or converting URLs from another format without adding the marker.

Related errors


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