{"record":{"id":"19ca081c6a4cc51a","repo":"sgl-project/sglang","slug":"unsupported-image-type-type-img-expected-torc","errorCode":null,"errorMessage":"Unsupported image type: {type(img)}. Expected torch.Tensor or PIL.Image.Image","messagePattern":"Unsupported image type: (.+?)\\. Expected torch\\.Tensor or PIL\\.Image\\.Image","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/multimodal/processors/mimo_v2.py","lineNumber":1427,"sourceCode":"    @classmethod\n    def get_visual_transform(\n        cls,\n        img: torch.Tensor | Image.Image,\n        factor: int,\n        min_pixels: int,\n        max_pixels: int,\n        device: Optional[torch.device] = None,\n    ):\n        if isinstance(img, torch.Tensor):\n            img_tensor = img.float()\n            _, h, w = img_tensor.shape\n        elif isinstance(img, Image.Image):\n            img = img.convert(\"RGB\")\n            w, h = img.size\n            img_array = np.array(img)\n            img_tensor = torch.from_numpy(img_array).permute(2, 0, 1).float()\n        else:\n            raise TypeError(\n                f\"Unsupported image type: {type(img)}. Expected torch.Tensor or PIL.Image.Image\"\n            )\n\n        if device is not None:\n            img_tensor = img_tensor.to(device)\n\n        h_bar, w_bar = cls.smart_resize(h, w, factor, min_pixels, max_pixels)\n\n        img_resized = F.interpolate(\n            img_tensor.unsqueeze(0),\n            size=(h_bar, w_bar),\n            mode=\"bilinear\",\n            align_corners=False,\n        )\n        img_standardized = cls.standardize_batch(img_resized).squeeze(0)\n\n        return img_standardized, w_bar, h_bar\n","sourceCodeStart":1409,"sourceCodeEnd":1445,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/multimodal/processors/mimo_v2.py#L1409-L1445","documentation":"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.","triggerScenarios":"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.","commonSituations":"Custom pipelines skipping fetch_image; passing cv2.imread/numpy output directly; version changes tightening the accepted types in the transform.","solutions":["Convert numpy/cv2 arrays to a PIL Image: Image.fromarray(arr) (cv2: cv2.cvtColor first for BGR→RGB)","Let the standard fetch_image path load paths/URLs/bytes into a PIL image before transform","Wrap tensors as torch float CHW tensors before calling"],"exampleFix":"# before\nimg = cv2.imread('x.png')            # numpy BGR\nproc.get_visual_transform(img)\n# after\nimg = Image.fromarray(cv2.cvtColor(cv2.imread('x.png'), cv2.COLOR_BGR2RGB))\nproc.get_visual_transform(img)","handlingStrategy":"type-guard","validationCode":"import numpy as np\nfrom PIL import Image\nimport torch\nassert isinstance(img, (torch.Tensor, Image.Image)), f'got {type(img)}; convert via Image.fromarray or load with fetch_image'","typeGuard":"from typing import Union, TypeGuard\nimport torch\nfrom PIL import Image\ndef is_transformable_image(img) -> TypeGuard[Union[torch.Tensor, Image.Image]]:\n    return isinstance(img, (torch.Tensor, Image.Image))","tryCatchPattern":"try:\n    t = proc.get_visual_transform(img)\nexcept TypeError as e:\n    if 'Unsupported image type' in str(e):\n        img = Image.fromarray(img) if isinstance(img, np.ndarray) else img\n        t = proc.get_visual_transform(img)\n    else:\n        raise","preventionTips":["Normalize all images to PIL before the transform stage","Convert cv2 BGR to RGB PIL explicitly","Rely on fetch_image for loading paths/URLs/bytes"],"tags":["image","type-error","transform","input-validation"],"backgroundTag":"unsupported-input-type","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}