{"record":{"id":"8942a2d99d9112ce","repo":"sgl-project/sglang","slug":"expected-chw-image-tensor-with-1-or-3-channels-go","errorCode":null,"errorMessage":"Expected CHW image tensor with 1 or 3 channels, got shape {shape}","messagePattern":"Expected CHW image tensor with 1 or 3 channels, got shape (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/multimodal/processors/step3_vl.py","lineNumber":43,"sourceCode":"Step3Image = Union[Image.Image, torch.Tensor]\nImageWithPatches = tuple[Step3Image, list[Step3Image], list[int] | None]\n\n\nclass GPUToTensor(torch.nn.Module):\n\n    def forward(\n        self, raw_image: Union[np.ndarray, Image.Image, torch.Tensor]\n    ) -> torch.Tensor:\n        if isinstance(raw_image, torch.Tensor):\n            image_tensor = raw_image\n            if image_tensor.ndim != 3:\n                raise TypeError(\n                    f\"Expected CHW image tensor, got shape {tuple(image_tensor.shape)}\"\n                )\n            if image_tensor.shape[0] == 1:\n                image_tensor = image_tensor.repeat(3, 1, 1)\n            elif image_tensor.shape[0] != 3:\n                raise TypeError(\n                    f\"Expected CHW image tensor with 1 or 3 channels, got shape {tuple(image_tensor.shape)}\"\n                )\n            if image_tensor.dtype == torch.uint8:\n                image_tensor = image_tensor.to(torch.float32).div(255)\n            elif not image_tensor.is_floating_point():\n                image_tensor = image_tensor.to(torch.float32)\n            return image_tensor.contiguous()\n        if isinstance(raw_image, Image.Image):\n            image_tensor = transforms.ToTensor()(raw_image)\n            if torch.cuda.is_available():\n                image_tensor = image_tensor.to(torch.device(\"cuda\"))\n            return image_tensor\n        if raw_image.ndim == 2:\n            raw_image = raw_image[:, :, None].repeat(3, -1)\n        if torch.cuda.is_available():\n            device = torch.device(\"cuda\")\n        else:\n            device = torch.device(\"cpu\")","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/multimodal/processors/step3_vl.py#L25-L61","documentation":"After confirming the tensor is 3D CHW, the Step3-VL transform requires the channel dimension to be exactly 1 (grayscale, auto-replicated to 3) or 3 (RGB). Any other first dimension (e.g. 2, 4 for RGBA, or an HWC tensor misread as CHW) fails this check. This catches layout mistakes where width or an alpha channel ends up in the channel slot.","triggerScenarios":"Passing a CHW tensor with shape[0] not in {1,3}: a 4-channel RGBA tensor (4,H,W), or an HWC tensor of a 4-pixel-wide image permuted incorrectly so a non-channel dim lands first.","commonSituations":"PNG images with alpha loaded as (4,H,W); masks saved as 2-channel float arrays; tensors converted from HWC without permute so channels land in the wrong axis.","solutions":["Convert RGBA to RGB before tensorizing: image.convert('RGB')","permute HWC to CHW so channels are dim 0","For grayscale masks, keep 1 channel — it is auto-expanded to 3"],"exampleFix":"# before\nimg = torch.from_numpy(rgba_array)  # (H, W, 4)\nimg = img.permute(2, 0, 1)\n# after\nimg = Image.fromarray(rgba_array).convert('RGB')\nimg = torch.from_numpy(np.array(img)).permute(2, 0, 1)","handlingStrategy":"validation","validationCode":"if isinstance(t, torch.Tensor) and t.ndim == 3:\n    assert t.shape[0] in (1, 3), f'bad channels: {tuple(t.shape)}'","typeGuard":"def has_valid_channels(t: torch.Tensor) -> bool:\n    return t.ndim == 3 and t.shape[0] in (1, 3)","tryCatchPattern":null,"preventionTips":["Convert RGBA/multi-channel images to RGB at load time (PIL .convert('RGB'))","Always permute HWC numpy arrays to CHW immediately after from_numpy"],"tags":["multimodal","image-processing","channels","step3-vl"],"backgroundTag":"invalid-tensor-shape","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}