sgl-project/sglang · error · ValueError
video latent spatial/time dims must be divisible by patch_si
Error message
video latent spatial/time dims must be divisible by patch_size: shape={list(latent.shape)}, patch_size={[pt, ph, pw]} What it means
minimax_h3_patchify_video_latent reshapes a [B,C,T,H,W] latent into patch grid tokens, which requires T divisible by pt, H by ph, and W by pw. If any spatial/temporal dim is not a multiple of the patch size, reshape is impossible and this ValueError reports both shape and patch_size.
Source
Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/packed_tokens.py:34
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
packed = latent.reshape(batch, channel, t, pt, h, ph, w, pw)
packed = torch.einsum("nctrhpwq->nthwcrpq", packed)
return packed.reshape(batch * t * h * w, channel * pt * ph * pw).contiguous()
def minimax_h3_unpatchify_video_tokens(
rows: torch.Tensor,
*,
latent_shape: Sequence[int],
patch_size: Sequence[int],
) -> torch.Tensor:
"""Unpack DiT video token rows into SGLang latent [B,C,T,H,W]."""
_rank(rows, "video token rows", 2)View on GitHub (pinned to 0132848349)
Solutions
- Pre-crop or pad the latent so T%pt==0, H%ph==0, W%pw==0 before patchify.
- Ensure upstream encoding (VAE stride / frame count) is chosen so latent dims are patch-multiples (e.g. frame counts multiple of pt*vale_temporal_stride).
- Verify the patch_size tuple matches the model's configured patchification.
Example fix
# before rows = minimax_h3_patchify_video_latent(latent, patch_size=(2, 16, 16)) # T=7 # after t = (latent.shape[2] // 2) * 2 rows = minimax_h3_patchify_video_latent(latent[:, :, :t], patch_size=(2, 16, 16))
Defensive patterns
Strategy: validation
Validate before calling
pt, ph, pw = patch_size b, c, t, h, w = latent.shape assert t % pt == 0 and h % ph == 0 and w % pw == 0, "latent dims not patch-divisible"
Type guard
def patch_divisible(latent: torch.Tensor, patch_size) -> bool:
pt, ph, pw = patch_size
_, _, t, h, w = latent.shape
return t % pt == 0 and h % ph == 0 and w % pw == 0 Prevention
- Choose frame counts that are multiples of pt times the VAE temporal stride.
- Crop latents to the patch grid before patchify; keep patch_size consistent with model config.
When it happens
Trigger: Calling with latent shape (1,16,7,64,64) and patch_size (2,16,16) — the temporal dim 7 is not divisible by 2; or a VAE that produced a spatial dim of 1000 with pw=128.
Common situations: Mixed-resolution inputs where images/videos are not pre-cropped to the patch grid; a VAE downsampling factor that yields odd temporal dims for short clips (e.g. 5 frames with temporal patch 2); changing patch_size in config without regenerating latents.
Related errors
- MiniMax-H3 adaln_t_table must have shape [N, D] with N >= 2,
- {name} must have length {length}, got {list(value)!r}
- {name} must be rank {rank}, got shape={list(tensor.shape)}
- video token dim {int(rows.shape[-1])} != patch volume * chan
- video rows {int(rows.shape[0])} must be divisible by t*h*w {
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/fe32936e3f586b9d.
Report an issue: GitHub.