sgl-project/sglang · error · ValueError

Invalid image: {image_file}

Error message

Invalid image: {image_file}

What it means

The image loader's final else branch: image_file is neither bytes, a URL string, a base64 string, a local path, nor a data URI — it has an unsupported type (None, int, Image already handled earlier, list, dict). The message echoes the value for debugging bad multimodal payloads.

Source

Thrown at python/sglang/srt/utils/common.py:1896

    elif isinstance(image_file, str) and image_file.startswith(("http://", "https://")):
        image = _load_image(image_file=image_file, gpu_image_decode=gpu_image_decode)
    elif isinstance(image_file, str) and image_file.startswith("file://"):
        image = _load_image(
            image_file=unquote(urlparse(image_file).path),
            gpu_image_decode=gpu_image_decode,
        )
    elif isinstance(image_file, str) and image_file.lower().endswith(
        image_extension_names
    ):
        image = _load_image(image_file=image_file, gpu_image_decode=gpu_image_decode)
    elif isinstance(image_file, str) and image_file.startswith("data:"):
        image = _load_image(image_file=image_file, gpu_image_decode=gpu_image_decode)
    elif isinstance(
        image_file, str
    ):  # Other formats, try to decode as base64 by default
        image = _load_image(image_file=image_file, gpu_image_decode=gpu_image_decode)
    else:
        raise ValueError(f"Invalid image: {image_file}")
    return image, image_size


def get_image_bytes(image_file: Union[str, bytes]) -> bytes:
    """Normalize various image inputs into raw bytes."""
    if isinstance(image_file, bytes):
        return image_file
    if image_file.startswith(("http://", "https://")):
        timeout = int(os.getenv("REQUEST_TIMEOUT", "3"))
        return download_remote_media(image_file, timeout=timeout)
    if image_file.startswith(("file://", "/")):
        with open(image_file, "rb") as f:
            return f.read()
    if isinstance(image_file, str) and image_file.startswith("data:"):
        _, encoded = image_file.split(",", 1)
        return pybase64.b64decode(encoded, validate=True)
    if isinstance(image_file, str):
        return pybase64.b64decode(image_file, validate=True)

View on GitHub (pinned to 0132848349)

Solutions

  1. Validate the image field is str/bytes at the API layer before decoding
  2. Return a 400 for null/missing image inputs instead of letting the worker raise
  3. If multiple images are supported, iterate and pass one at a time

Example fix

# before
image, size = load_image(req.get('image'))  # None -> ValueError
# after
img = req.get('image')
if not isinstance(img, (str, bytes)): raise HTTPException(400, 'image must be a string or bytes')
image, size = load_image(img)
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(image_file, (str, bytes)):
    return HTTPException(400, 'image must be a string (url/path/base64) or bytes')
image, size = load_image(image_file)

Type guard

def is_image_input(v) -> bool:
    return isinstance(v, (str, bytes)) and len(v) > 0

Try / catch

try:
    image, size = load_image(image_file)
except ValueError as e:
    if 'Invalid image' in str(e):
        return HTTPException(400, str(e))
    raise

Prevention

When it happens

Trigger: Calling the top-level image loader (in fetch/decode pipeline) with None or a non-str/bytes object — e.g. request JSON {"image": null} or a list where a single image string was expected.

Common situations: Missing image key defaulting to None; frontend sending arrays; template bugs forwarding the wrong field; protobuf/JSON typing surprises.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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