sgl-project/sglang · error · ValueError

data URI must contain a comma separator

Error message

data URI must contain a comma separator

What it means

When parsing a 'data:' base64 material URI, _base64_uri_payload_start requires a ',' separator between the header and the payload (RFC data-URI syntax). A data: URI with no comma cannot be split into header/payload, so the loader refuses it.

Source

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

    if isinstance(registry, dict):
        for owner in selected:
            paths = registry.pop(owner, [])
            if isinstance(paths, (list, tuple)):
                for path in paths:
                    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")

View on GitHub (pinned to 0132848349)

Solutions

  1. Fix the producer to emit full 'data:<mediatype>;base64,<payload>' URIs
  2. Validate the URI starts with 'data:' and contains ',' before submitting the request
  3. Log the offending URI prefix (truncated) at ingestion to catch generation bugs early

Example fix

// before
uri = f"data:{media_type};base64"  # payload never appended
// after
uri = f"data:{media_type};base64,{base64.b64encode(blob).decode('ascii')}"
Defensive patterns

Strategy: validation

Validate before calling

if uri.startswith('data:') and ',' not in uri:
    raise ValueError('rejecting malformed data URI (no comma) at ingestion')

Type guard

def is_wellformed_data_uri(uri: str) -> bool:
    return uri.startswith('data:') and ',' in uri and uri.index(',') <= 128

Prevention

When it happens

Trigger: Streaming a material URI like 'data:image/png;base64' (truncated, payload missing) or a malformed data URI that never contains ',' via _stream_base64_material.

Common situations: Truncated material URIs from LLM-generated content or prompt templates, string concatenation bugs that drop the payload, or upstream URL-encoding that strips the comma.

Related errors


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