sgl-project/sglang · error · RuntimeError
nvImageCodec returned an invalid JPEG tensor: shape={tuple(i
Error message
nvImageCodec returned an invalid JPEG tensor: shape={tuple(image.shape)}, dtype={image.dtype} What it means
decode_jpeg_with_fancy_upsampling got a tensor back from nvImageCodec but it is not a 3D uint8 CHW tensor with 3 channels. The guard checks ndim==3, shape[0]==3, dtype==uint8, so grayscale (1 channel), RGBA (4 channels), or unexpected layouts/dtypes trigger this RuntimeError.
Source
Thrown at python/sglang/srt/utils/nvjpeg_decoder.py:82
@lru_cache(maxsize=None)
def _get_decoder_pool(device_id: int) -> _NvJpegDecoderPool:
return _NvJpegDecoderPool(device_id)
def decode_jpeg_with_fancy_upsampling(image_bytes: bytes) -> torch.Tensor:
"""Decode a JPEG to contiguous CHW RGB uint8 on the current CUDA device.
torchvision's CUDA JPEG decoder creates nvJPEG with its default flags,
which use nearest-neighbor chroma upsampling. nvImageCodec exposes nvJPEG's
interpolated ("fancy") upsampling and exports the result to PyTorch through
DLPack without copying it.
"""
device_id = torch.cuda.current_device()
image = _get_decoder_pool(device_id).decode(image_bytes)
if image.ndim != 3 or image.shape[0] != 3 or image.dtype != torch.uint8:
raise RuntimeError(
"nvImageCodec returned an invalid JPEG tensor: "
f"shape={tuple(image.shape)}, dtype={image.dtype}"
)
return image
View on GitHub (pinned to 0132848349)
Solutions
- Convert grayscale inputs to RGB before submission (PIL convert('RGB')) or pre-check the JPEG component count
- Add a try/except with CPU fallback that normalizes to RGB
- Pin/verify the nvImageCodec version and decode params (output color format) used by the pool
Example fix
# before
img = decode_jpeg_with_fancy_upsampling(data) # grayscale JPEG -> RuntimeError
# after
try:
img = decode_jpeg_with_fancy_upsampling(data)
except RuntimeError:
img = cpu_decode_rgb(data) Defensive patterns
Strategy: try-catch
Validate before calling
def jpeg_channel_count(path) -> int:
from PIL import Image
with Image.open(path) as im:
return len(im.getbands()) Type guard
null
Try / catch
try:
img = decode_jpeg_with_fancy_upsampling(data)
except RuntimeError as e:
if 'invalid JPEG tensor' in str(e):
img = decode_with_pil(data).convert('RGB')
else:
raise Prevention
- Convert grayscale/CMYK images to RGB in preprocessing
- Pin nvImageCodec version in deployments
- Add dataset scans for 1-/4-channel JPEGs before GPU serving
When it happens
Trigger: Decoding a grayscale JPEG (nvImageCodec yields 1-channel), an image decoded to a non-standard layout, or a colorspace config mismatch in the decode params producing non-uint8 output.
Common situations: Datasets mixing RGB and grayscale JPEGs; images with unusual color spaces; version changes in nvImageCodec altering output layout.
Related errors
- nvImageCodec could not decode the JPEG image
- Z-Image text embeddings must have shape [seq, dim] or [batch
- Z-Image caption tensor must have rank 2 or 3
- {selection_error}{component_suffix}
- No compatible attention backend is available{component_suffi
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/6075f16d8abd8c16.
Report an issue: GitHub.