sgl-project/sglang · error · TypeError

Unsupported image type: {type(image)}

Error message

Unsupported image type: {type(image)}

What it means

A preprocessing helper in the MoVA multimodal pipeline only accepts PIL Images or torch Tensors for condition images. When _center_crop_and_resize receives any other object (e.g. a numpy array, str path, or URL), it raises a TypeError naming the offending type. It is a strict input-contract check before cropping/resizing condition images.

Source

Thrown at python/sglang/multimodal_gen/configs/pipeline_configs/mova.py:70

    audio_vae_type: str = "dac"
    boundary_ratio: float | None = 0.9

    # temporal alignment: MOVA expects (num_frames - 1) % 4 == 0
    time_division_factor: int = 4
    time_division_remainder: int = 1

    def get_model_deployment_config(self) -> ModelDeploymentConfig:
        return ModelDeploymentConfig(
            dit_layerwise_offload_modes=("auto", "memory"),
            keep_resident_min_available_gb=130,
            keep_resident_components=("dit", "vae"),
        )

    def _center_crop_and_resize(
        self, image: torch.Tensor | Image.Image, target_height: int, target_width: int
    ) -> torch.Tensor | Image.Image:
        if not isinstance(image, (Image.Image, torch.Tensor)):
            raise TypeError(f"Unsupported image type: {type(image)}")
        if isinstance(image, Image.Image):
            image = torch.from_numpy(np.array(image))

        if image.ndim == 2:
            image = image[..., None]

        if not image.dtype.is_floating_point:
            image = image.to(torch.float32).div(255.0)

        if image.ndim == 3:
            if image.shape[0] in (1, 3, 4) and image.shape[-1] not in (1, 3, 4):
                image = image.unsqueeze(0)
            else:
                image = image.permute(2, 0, 1).unsqueeze(0)
        elif image.ndim == 4:
            if image.shape[1] not in (1, 3, 4) and image.shape[-1] in (1, 3, 4):
                image = image.permute(0, 3, 1, 2)

View on GitHub (pinned to 0132848349)

Solutions

  1. Convert the input before calling: img = Image.fromarray(cv2.cvtColor(arr, cv2.COLOR_BGR2RGB)) or torch.from_numpy(arr)
  2. If you have a path, open it with PIL: image = Image.open(path).convert('RGB')
  3. If passing frames from numpy pipelines, wrap once at the boundary: torch.from_numpy(np.asarray(pil_or_frame))

Example fix

# before
image = cv2.imread('cond.jpg')  # numpy BGR
pipeline.preprocess_condition_image(image)

# after
image = Image.fromarray(cv2.cvtColor(cv2.imread('cond.jpg'), cv2.COLOR_BGR2RGB))
pipeline.preprocess_condition_image(image)
Defensive patterns

Strategy: type-guard

Validate before calling

from PIL import Image
import torch

def is_valid_condition_image(x):
    return isinstance(x, (Image.Image, torch.Tensor)) and x is not None

assert is_valid_condition_image(image), f"bad type: {type(image)}"

Type guard

def is_condition_image(x) -> bool:
    return isinstance(x, (Image.Image, torch.Tensor))

Try / catch

try:
    latents = pipeline.preprocess_condition_image(image)
except TypeError as e:
    raise ValueError(f"Condition image must be PIL or Tensor, got {type(image)}") from e

Prevention

When it happens

Trigger: Calling preprocess_condition_image (MoVA pipeline) with a numpy ndarray, file path string, bytes, or None instead of a PIL.Image.Image or torch.Tensor. Loading an image with cv2.imread or np.asarray and passing it directly without converting to PIL/Tensor.

Common situations: Developer loads condition images with OpenCV (BGR ndarray) instead of PIL; receives a raw numpy array from a dataloader or decoded video frame; passes a lazy path/URL object assuming the pipeline will fetch it.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/522feed015ab51f4. Report an issue: GitHub.