sgl-project/sglang · error · TypeError

Unsupported image type: {type}

Error message

Unsupported image type: {type}

What it means

ImagePatcher.get_image_size accepts only PIL.Image.Image instances and 3D CHW torch tensors. Anything else — numpy arrays, paths, bytes, tf tensors — reaches the final raise. This is a deliberate strict contract: the patcher needs pixel dimensions and only knows how to extract them from those two types.

Source

Thrown at python/sglang/srt/multimodal/processors/step3_vl.py:128

    def __call__(self, image, is_patch=False):
        if is_patch:
            return {"pixel_values": self.patch_transform(image).unsqueeze(0)}
        else:
            return {"pixel_values": self.transform(image).unsqueeze(0)}


class ImagePatcher:
    def get_image_size(self, img: Step3Image) -> tuple[int, int]:
        if isinstance(img, Image.Image):
            return img.size
        if isinstance(img, torch.Tensor):
            if img.ndim != 3:
                raise TypeError(
                    f"Expected CHW image tensor, got shape {tuple(img.shape)}"
                )
            return int(img.shape[-1]), int(img.shape[-2])
        raise TypeError(f"Unsupported image type: {type(img)}")

    def determine_window_size(self, long: int, short: int) -> int:
        if long <= 728:
            return short if long / short > 1.5 else 0
        return min(short, 504) if long / short > 4 else 504

    def slide_window(
        self,
        width: int,
        height: int,
        sizes: list[tuple[int, int]],
        steps: list[tuple[int, int]],
        img_rate_thr: float = 0.6,
    ) -> tuple[list[tuple[int, int, int, int]], tuple[int, int]]:
        assert 1 >= img_rate_thr >= 0, "The `img_rate_thr` should lie in 0~1"
        windows = []
        # Sliding windows.
        for size, step in zip(sizes, steps):

View on GitHub (pinned to 0132848349)

Solutions

  1. Convert numpy to PIL: Image.fromarray(cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB))
  2. Load from path: Image.open(path).convert('RGB')
  3. Convert numpy to a CHW float tensor if PIL is unavailable

Example fix

# before
patched = patcher(cv2_frame)  # np.ndarray
# after
from PIL import Image
patched = patcher(Image.fromarray(cv2.cvtColor(cv2_frame, cv2.COLOR_BGR2RGB)))
Defensive patterns

Strategy: type-guard

Validate before calling

if isinstance(img, np.ndarray):
    img = Image.fromarray(img[..., ::-1]) if img.shape[-1] == 3 else Image.fromarray(img)

Type guard

def is_supported_image(x) -> bool:
    import PIL.Image, torch
    return isinstance(x, (PIL.Image.Image,)) or (isinstance(x, torch.Tensor) and x.ndim == 3)

Prevention

When it happens

Trigger: Calling ImagePatcher.__call__ or square_pad with a np.ndarray, file path string, raw bytes, or any non-PIL/non-tensor object.

Common situations: Passing image paths or numpy frames (common from OpenCV/video pipelines) expecting the processor to do the loading; wrapping images in custom container objects.

Related errors


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