sgl-project/sglang · error · ValueError

{name} must be rank {rank}, got shape={list(tensor.shape)}

Error message

{name} must be rank {rank}, got shape={list(tensor.shape)}

What it means

The _rank helper enforces the tensor rank (number of dimensions) expected by the minimax_h3 token packing functions: video latents and video token rows must be rank 5 and 2 respectively, audio token inputs rank-checked via minimax_h3_unpack_audio_tokens. Passing a tensor with the wrong number of dims fails immediately with the observed shape in the message.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/packed_tokens.py:20

from __future__ import annotations

from collections.abc import Sequence

import torch


def _int_tuple(value: Sequence[int], name: str, length: int) -> tuple[int, ...]:
    if len(value) != length:
        raise ValueError(f"{name} must have length {length}, got {list(value)!r}")
    out = tuple(int(item) for item in value)
    if any(item <= 0 for item in out):
        raise ValueError(f"{name} values must be positive, got {list(value)!r}")
    return out


def _rank(tensor: torch.Tensor, name: str, rank: int) -> None:
    if tensor.ndim != rank:
        raise ValueError(f"{name} must be rank {rank}, got shape={list(tensor.shape)}")


def minimax_h3_patchify_video_latent(
    latent: torch.Tensor,
    *,
    patch_size: Sequence[int],
) -> torch.Tensor:
    """Pack SGLang video latent [B,C,T,H,W] into DiT token rows."""

    _rank(latent, "video latent", 5)
    pt, ph, pw = _int_tuple(patch_size, "patch_size", 3)
    batch, channel, full_t, full_h, full_w = (int(dim) for dim in latent.shape)
    if full_t % pt or full_h % ph or full_w % pw:
        raise ValueError(
            "video latent spatial/time dims must be divisible by patch_size: "
            f"shape={list(latent.shape)}, patch_size={[pt, ph, pw]}"
        )
    t, h, w = full_t // pt, full_h // ph, full_w // pw

View on GitHub (pinned to 0132848349)

Solutions

  1. Reshape to the documented rank: video latent [B,C,T,H,W] (rank 5), video token rows rank 2, audio tokens per the audio unpacker's expected rank.
  2. Audit squeeze/unsqueeze calls in the preceding stage; the mismatch is usually one dim off.
  3. Print tensor.shape right before the call during debugging to confirm.

Example fix

# before
rows = minimax_h3_patchify_video_latent(latent[0], patch_size=patch)  # rank-4 input

# after
rows = minimax_h3_patchify_video_latent(latent, patch_size=patch)  # keep [B,C,T,H,W]
Defensive patterns

Strategy: validation

Validate before calling

assert latent.ndim == 5, f"expected [B,C,T,H,W], got shape {list(latent.shape)}"
assert rows.ndim == 2, f"expected rank-2 token rows, got shape {list(rows.shape)}"

Type guard

import torch

def is_batched_video_latent(t: torch.Tensor) -> bool:
    return t.ndim == 5

Prevention

When it happens

Trigger: Passing a [B,T,H,W,C] (rank 5 but channels-last, still passes rank check but wrong layout) vs a [C,T,H,W] single-sample (rank 4) video latent; passing video token rows of rank 3 (e.g. with an extra batch dim) to minimax_h3_unpatchify_video_tokens.

Common situations: Unsqueezing/squeezing a batch dim inconsistently across pipeline stages; feeding a per-sample latent from a loop (missing batch dim) into a function expecting batched input; tensor arriving as rank-3 after a .mean() or slicing bug.

Related errors


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