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 // pwView on GitHub (pinned to 0132848349)
Solutions
- 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.
- Audit squeeze/unsqueeze calls in the preceding stage; the mismatch is usually one dim off.
- 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
- Standardize batch handling (always keep the batch dim) across pipeline stages.
- Log tensor shapes at stage boundaries during development.
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
- MiniMax-H3 adaln_t_table must have shape [N, D] with N >= 2,
- video latent spatial/time dims must be divisible by patch_si
- video token dim {int(rows.shape[-1])} != patch volume * chan
- video rows {int(rows.shape[0])} must be divisible by t*h*w {
- `dt_bias` must have {HV * K} elements (got {dt_bias.numel()}
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/1eedadc47789bc43.
Report an issue: GitHub.