sgl-project/sglang · error · TypeError

Unsupported image type: {type(img)}. Expected torch.Tensor o

Error message

Unsupported image type: {type(img)}. Expected torch.Tensor or PIL.Image.Image

What it means

Raised by get_visual_transform when img is neither a torch.Tensor (CHW/frames) nor a PIL.Image.Image. Those are the only two in-memory image representations the transform accepts; numpy arrays, paths, URLs, bytes, or cv2 images all fail here.

Source

Thrown at python/sglang/srt/multimodal/processors/mimo_v2.py:1427

    @classmethod
    def get_visual_transform(
        cls,
        img: torch.Tensor | Image.Image,
        factor: int,
        min_pixels: int,
        max_pixels: int,
        device: Optional[torch.device] = None,
    ):
        if isinstance(img, torch.Tensor):
            img_tensor = img.float()
            _, h, w = img_tensor.shape
        elif isinstance(img, Image.Image):
            img = img.convert("RGB")
            w, h = img.size
            img_array = np.array(img)
            img_tensor = torch.from_numpy(img_array).permute(2, 0, 1).float()
        else:
            raise TypeError(
                f"Unsupported image type: {type(img)}. Expected torch.Tensor or PIL.Image.Image"
            )

        if device is not None:
            img_tensor = img_tensor.to(device)

        h_bar, w_bar = cls.smart_resize(h, w, factor, min_pixels, max_pixels)

        img_resized = F.interpolate(
            img_tensor.unsqueeze(0),
            size=(h_bar, w_bar),
            mode="bilinear",
            align_corners=False,
        )
        img_standardized = cls.standardize_batch(img_resized).squeeze(0)

        return img_standardized, w_bar, h_bar

View on GitHub (pinned to 0132848349)

Solutions

  1. Convert numpy/cv2 arrays to a PIL Image: Image.fromarray(arr) (cv2: cv2.cvtColor first for BGR→RGB)
  2. Let the standard fetch_image path load paths/URLs/bytes into a PIL image before transform
  3. Wrap tensors as torch float CHW tensors before calling

Example fix

# before
img = cv2.imread('x.png')            # numpy BGR
proc.get_visual_transform(img)
# after
img = Image.fromarray(cv2.cvtColor(cv2.imread('x.png'), cv2.COLOR_BGR2RGB))
proc.get_visual_transform(img)
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np
from PIL import Image
import torch
assert isinstance(img, (torch.Tensor, Image.Image)), f'got {type(img)}; convert via Image.fromarray or load with fetch_image'

Type guard

from typing import Union, TypeGuard
import torch
from PIL import Image
def is_transformable_image(img) -> TypeGuard[Union[torch.Tensor, Image.Image]]:
    return isinstance(img, (torch.Tensor, Image.Image))

Try / catch

try:
    t = proc.get_visual_transform(img)
except TypeError as e:
    if 'Unsupported image type' in str(e):
        img = Image.fromarray(img) if isinstance(img, np.ndarray) else img
        t = proc.get_visual_transform(img)
    else:
        raise

Prevention

When it happens

Trigger: Calling process_image / get_visual_transform with img being a numpy array, cv2 BGR image, file path string, or base64 bytes — types accepted by fetch_image but not by the transform stage.

Common situations: Custom pipelines skipping fetch_image; passing cv2.imread/numpy output directly; version changes tightening the accepted types in the transform.

Related errors


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