sgl-project/sglang · error · ValueError

Cosmos3 observation image arrays must have shape [H, W] or [

Error message

Cosmos3 observation image arrays must have shape [H, W] or [H, W, C], got {tuple(item.shape)}

What it means

numpy image arrays for Cosmos3 must be 2D grayscale [H, W] or 3D [H, W, C]; other ranks raise this ValueError with the offending shape. Note [B,H,W,C] batched arrays are handled elsewhere — per-item arrays here must be single images.

Source

Thrown at python/sglang/multimodal_gen/runtime/entrypoints/action/cosmos3.py:101

            )
        image = next(iter(images.values()))

    if isinstance(image, (list, tuple)):
        images = list(image)
    elif isinstance(image, np.ndarray) and image.ndim == 4:
        images = list(image)
    else:
        images = [image]

    normalized_images: list[Any] = []
    for item in images:
        if not isinstance(item, np.ndarray):
            normalized_images.append(item)
            continue
        if item.dtype != np.uint8:
            raise ValueError("Cosmos3 observation image arrays must use uint8 dtype")
        if item.ndim not in (2, 3):
            raise ValueError(
                "Cosmos3 observation image arrays must have shape [H, W] "
                f"or [H, W, C], got {tuple(item.shape)}"
            )
        normalized_images.append(Image.fromarray(item))
    return normalized_images


def _action_prompt(prompt: Any, batch_size: int) -> str | list[str]:
    if isinstance(prompt, str):
        return prompt if batch_size == 1 else [prompt] * batch_size
    if not isinstance(prompt, (list, tuple)) or not prompt:
        raise ValueError("Cosmos3 action prompt must be a string or non-empty list")
    if not all(isinstance(item, str) for item in prompt):
        raise ValueError("Cosmos3 action prompt list must contain only strings")
    prompts = list(prompt)
    if len(prompts) == 1 and batch_size > 1:
        prompts *= batch_size
    if len(prompts) != batch_size:

View on GitHub (pinned to 0132848349)

Solutions

  1. Transpose/reshape to [H,W] or [H,W,C]: arr = arr.transpose(1,2,0) for CHW->HWC
  2. Remove batch/time dims: arr.squeeze() or arr[0] / arr[:, t]
  3. For batches, pass a list of [H,W,C] uint8 arrays

Example fix

# before
image = chw_tensor.numpy()  # shape [3, 224, 224] -> error

# after
image = chw_tensor.permute(1, 2, 0).numpy().astype(np.uint8)  # [224, 224, 3]
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np
def ensure_hwc_uint8(arr: np.ndarray) -> np.ndarray:
    assert arr.ndim in (2, 3), f"bad image rank {arr.shape}"
    if arr.ndim == 3 and arr.shape[0] in (1, 3) and arr.shape[0] < arr.shape[-1]:
        arr = arr.transpose(1, 2, 0)  # CHW -> HWC heuristic
    return ensure_uint8(arr)

Type guard

def is_valid_image_shape(a) -> bool:
    return not isinstance(a, np.ndarray) or (a.dtype == np.uint8 and a.ndim in (2, 3))

Prevention

When it happens

Trigger: Passing a [B,H,W,C] batched array that ends up iterated per-item incorrectly, a flattened [H*W] vector, [C,H,W] channel-first tensor converted to numpy, or an [H,W,C,T] video clip.

Common situations: Images converted from torch tensors keeping channel-first layout; video frames with an extra time dimension; already-batched arrays reaching a code path expecting single images.

Related errors


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