{"record":{"id":"fe32936e3f586b9d","repo":"sgl-project/sglang","slug":"video-latent-spatial-time-dims-must-be-divisible-b","errorCode":null,"errorMessage":"video latent spatial/time dims must be divisible by patch_size: shape={list(latent.shape)}, patch_size={[pt, ph, pw]}","messagePattern":"video latent spatial/time dims must be divisible by patch_size: shape=(.+?), patch_size=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/packed_tokens.py","lineNumber":34,"sourceCode":"\n\ndef _rank(tensor: torch.Tensor, name: str, rank: int) -> None:\n    if tensor.ndim != rank:\n        raise ValueError(f\"{name} must be rank {rank}, got shape={list(tensor.shape)}\")\n\n\ndef minimax_h3_patchify_video_latent(\n    latent: torch.Tensor,\n    *,\n    patch_size: Sequence[int],\n) -> torch.Tensor:\n    \"\"\"Pack SGLang video latent [B,C,T,H,W] into DiT token rows.\"\"\"\n\n    _rank(latent, \"video latent\", 5)\n    pt, ph, pw = _int_tuple(patch_size, \"patch_size\", 3)\n    batch, channel, full_t, full_h, full_w = (int(dim) for dim in latent.shape)\n    if full_t % pt or full_h % ph or full_w % pw:\n        raise ValueError(\n            \"video latent spatial/time dims must be divisible by patch_size: \"\n            f\"shape={list(latent.shape)}, patch_size={[pt, ph, pw]}\"\n        )\n    t, h, w = full_t // pt, full_h // ph, full_w // pw\n    packed = latent.reshape(batch, channel, t, pt, h, ph, w, pw)\n    packed = torch.einsum(\"nctrhpwq->nthwcrpq\", packed)\n    return packed.reshape(batch * t * h * w, channel * pt * ph * pw).contiguous()\n\n\ndef minimax_h3_unpatchify_video_tokens(\n    rows: torch.Tensor,\n    *,\n    latent_shape: Sequence[int],\n    patch_size: Sequence[int],\n) -> torch.Tensor:\n    \"\"\"Unpack DiT video token rows into SGLang latent [B,C,T,H,W].\"\"\"\n\n    _rank(rows, \"video token rows\", 2)","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/packed_tokens.py#L16-L52","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nrows = minimax_h3_patchify_video_latent(latent, patch_size=(2, 16, 16))  # T=7\n\n# after\nt = (latent.shape[2] // 2) * 2\nrows = minimax_h3_patchify_video_latent(latent[:, :, :t], patch_size=(2, 16, 16))","handlingStrategy":"validation","validationCode":"pt, ph, pw = patch_size\nb, c, t, h, w = latent.shape\nassert t % pt == 0 and h % ph == 0 and w % pw == 0, \"latent dims not patch-divisible\"","typeGuard":"def patch_divisible(latent: torch.Tensor, patch_size) -> bool:\n    pt, ph, pw = patch_size\n    _, _, t, h, w = latent.shape\n    return t % pt == 0 and h % ph == 0 and w % pw == 0","tryCatchPattern":null,"preventionTips":["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."],"tags":["validation","tensor-shape","patchify","divisibility","minimax-h3"],"backgroundTag":"dimension-not-divisible","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}