{"record":{"id":"a23f1bf113a84ee7","repo":"sgl-project/sglang","slug":"kimi-gpu-preprocessing-expects-raw-uint8-pixels-g","errorCode":null,"errorMessage":"Kimi GPU preprocessing expects raw uint8 pixels, got {image.dtype}","messagePattern":"Kimi GPU preprocessing expects raw uint8 pixels, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/multimodal/processors/kimi_k25.py","lineNumber":134,"sourceCode":"\ndef _ensure_chw_rgb(image: torch.Tensor) -> torch.Tensor:\n    \"\"\"Coerce an already-decoded (C, H, W) image tensor to 3-channel RGB.\n\n    PIL inputs are RGB-normalized by _pil_to_cuda_chw, but pre-decoded\n    tensor inputs (e.g. nvJPEG / cached CUDA tensors) keep their native\n    channel count. Grayscale (1ch) or RGBA (4ch) images then break the\n    downstream torch.cat over a batch of images, which requires a\n    consistent channel dimension. Normalize every tensor to 3 channels.\n\n    Also move the tensor to the GPU (matching _pil_to_cuda_chw) so a CPU\n    input does not trip a device mismatch against the CUDA normalization\n    constants downstream. No-op if already on the device.\n    \"\"\"\n    if image.dtype != torch.uint8:\n        # Raw 0-255 is load-bearing downstream: the resize rounds to integers\n        # and the normalization folds in a 1/255 scale, so a normalized float\n        # image would collapse to 0/1 and then be rescaled.\n        raise ValueError(\n            f\"Kimi GPU preprocessing expects raw uint8 pixels, got {image.dtype}\"\n        )\n    image = image.cuda()\n    if image.dim() == 2:  # (H, W) grayscale -> (1, H, W)\n        image = image.unsqueeze(0)\n    c = image.shape[0]\n    if c == 3:\n        return image\n    if c == 1:\n        return image.repeat(3, 1, 1)\n    # RGBA or other multi-channel layouts: keep the first 3 channels.\n    return image[:3]\n\n\ndef _resize_bicubic_if_needed(\n    image: torch.Tensor, target_height: int, target_width: int\n) -> torch.Tensor:\n    \"\"\"Track the checkpoint processor's ``PIL.Image.resize(..., BICUBIC)``.","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/multimodal/processors/kimi_k25.py#L116-L152","documentation":"Kimi K2.5 GPU preprocessing needs raw 0-255 uint8 pixels: the resize kernel rounds to integers and normalization folds in 1/255 scaling. A float tensor (e.g. already-normalized 0-1) would collapse to 0/1 after rounding, so the processor refuses it with ValueError instead of producing garbage.","triggerScenarios":"Calling _to_cuda_chw / _ensure_chw_rgb with a float image tensor (already normalized or 0-1 floats) instead of a uint8 HxWx3/CHW tensor.","commonSituations":"Reusing images already preprocessed by another pipeline (HF processor output, torchvision ToTensor, normalized caches) and feeding them directly into Kimi's GPU path.","solutions":["Pass raw uint8 images (PIL->np.asarray, cv2 BGR->RGB uint8) into the processor","If you only have normalized floats, denormalize and rescale back to uint8 before sending","Keep one canonical raw-image path and do normalization only inside the processor"],"exampleFix":"# before\nimg = torchvision.transforms.ToTensor()(pil)  # float 0-1 CHW\nto_cuda_chw(img)\n\n# after\nimg = torch.from_numpy(np.asarray(pil.convert(\"RGB\")))  # uint8 HWC\nto_cuda_chw(img)","handlingStrategy":"type-guard","validationCode":"assert image.dtype == torch.uint8, f\"need raw uint8 pixels, got {image.dtype}\"","typeGuard":"def is_raw_uint8(img: torch.Tensor) -> bool:\n    return img.dtype == torch.uint8","tryCatchPattern":"try:\n    chw = _to_cuda_chw(image)\nexcept ValueError as e:\n    if \"raw uint8\" in str(e):\n        image = (image.clamp(0, 1) * 255).to(torch.uint8)  # denormalize\n        chw = _to_cuda_chw(image)\n    else:\n        raise","preventionTips":["Feed raw PIL/numpy uint8 images; let the processor normalize","Never reuse outputs of other preprocessors as inputs","Keep one canonical raw-image representation in your pipeline"],"tags":["kimi","k25","multimodal","dtype-validation","preprocessing"],"backgroundTag":"image-dtype-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}