sgl-project/sglang · error · TypeError
Expected CHW image tensor with 1 or 3 channels, got shape {s
Error message
Expected CHW image tensor with 1 or 3 channels, got shape {shape} What it means
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.
Source
Thrown at python/sglang/srt/multimodal/processors/step3_vl.py:43
Step3Image = Union[Image.Image, torch.Tensor]
ImageWithPatches = tuple[Step3Image, list[Step3Image], list[int] | None]
class GPUToTensor(torch.nn.Module):
def forward(
self, raw_image: Union[np.ndarray, Image.Image, torch.Tensor]
) -> torch.Tensor:
if isinstance(raw_image, torch.Tensor):
image_tensor = raw_image
if image_tensor.ndim != 3:
raise TypeError(
f"Expected CHW image tensor, got shape {tuple(image_tensor.shape)}"
)
if image_tensor.shape[0] == 1:
image_tensor = image_tensor.repeat(3, 1, 1)
elif image_tensor.shape[0] != 3:
raise TypeError(
f"Expected CHW image tensor with 1 or 3 channels, got shape {tuple(image_tensor.shape)}"
)
if image_tensor.dtype == torch.uint8:
image_tensor = image_tensor.to(torch.float32).div(255)
elif not image_tensor.is_floating_point():
image_tensor = image_tensor.to(torch.float32)
return image_tensor.contiguous()
if isinstance(raw_image, Image.Image):
image_tensor = transforms.ToTensor()(raw_image)
if torch.cuda.is_available():
image_tensor = image_tensor.to(torch.device("cuda"))
return image_tensor
if raw_image.ndim == 2:
raw_image = raw_image[:, :, None].repeat(3, -1)
if torch.cuda.is_available():
device = torch.device("cuda")
else:
device = torch.device("cpu")View on GitHub (pinned to 0132848349)
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
Example fix
# before
img = torch.from_numpy(rgba_array) # (H, W, 4)
img = img.permute(2, 0, 1)
# after
img = Image.fromarray(rgba_array).convert('RGB')
img = torch.from_numpy(np.array(img)).permute(2, 0, 1) Defensive patterns
Strategy: validation
Validate before calling
if isinstance(t, torch.Tensor) and t.ndim == 3:
assert t.shape[0] in (1, 3), f'bad channels: {tuple(t.shape)}' Type guard
def has_valid_channels(t: torch.Tensor) -> bool:
return t.ndim == 3 and t.shape[0] in (1, 3) Prevention
- Convert RGBA/multi-channel images to RGB at load time (PIL .convert('RGB'))
- Always permute HWC numpy arrays to CHW immediately after from_numpy
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Expected CHW image tensor, got shape {shape}
- Unsupported image type: {type}
- Unsupported image type: {type(image)}
- Step3-VL image item is missing num_patches.
- Step3-VL image item has num_patches > 0 but no patch_pixel_v
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/8942a2d99d9112ce.
Report an issue: GitHub.