{"record":{"id":"6febd28b2e502b0b","repo":"sgl-project/sglang","slug":"video-rows-int-rows-shape-0-must-be-divisible","errorCode":null,"errorMessage":"video rows {int(rows.shape[0])} must be divisible by t*h*w {rows_per_sample} for latent_shape={list(latent_shape)}","messagePattern":"video rows (.+?) must be divisible by t\\*h\\*w (.+?) for latent_shape=(.+?)","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":64,"sourceCode":"    *,\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)\n    t, h, w, channel = _int_tuple(latent_shape, \"latent_shape\", 4)\n    pt, ph, pw = _int_tuple(patch_size, \"patch_size\", 3)\n    expected_dim = pt * ph * pw * channel\n    if int(rows.shape[-1]) != expected_dim:\n        raise ValueError(\n            f\"video token dim {int(rows.shape[-1])} != patch volume * channel \"\n            f\"{expected_dim} for latent_shape={list(latent_shape)}, \"\n            f\"patch_size={[pt, ph, pw]}\"\n        )\n    rows_per_sample = t * h * w\n    if int(rows.shape[0]) % rows_per_sample:\n        raise ValueError(\n            f\"video rows {int(rows.shape[0])} must be divisible by t*h*w \"\n            f\"{rows_per_sample} for latent_shape={list(latent_shape)}\"\n        )\n    packed = rows.reshape(-1, t, h, w, channel, pt, ph, pw)\n    latent = torch.einsum(\"nthwcrpq->nctrhpwq\", packed)\n    return latent.reshape(-1, channel, t * pt, h * ph, w * pw).contiguous()\n\n\ndef minimax_h3_unpack_audio_tokens(\n    rows: torch.Tensor,\n    *,\n    audio_t: int,\n    audio_channel: int,\n) -> torch.Tensor:\n    \"\"\"Unpack DiT audio token rows into SGLang audio VAE latent [C,latent_dim,T].\"\"\"\n\n    _rank(rows, \"audio token rows\", 2)\n    audio_t = int(audio_t)","sourceCodeStart":46,"sourceCodeEnd":82,"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#L46-L82","documentation":"The unpatchify path requires the total number of token rows to be a whole multiple of t*h*w (rows per video sample implied by latent_shape). A remainder means rows cannot be evenly reshaped into per-frame patch grids, indicating a batch/row-count inconsistency between the token tensor and the declared latent shape.","triggerScenarios":"Passing rows for 5.5 samples' worth of grids relative to latent_shape, e.g. rows.shape[0]=1000 with t*h*w=256 (1000%256!=0); commonly concatenating reference and target video rows but declaring latent_shape for only one video.","commonSituations":"Concatenating multiple videos' rows (hybrid ref+target layouts) while unpatchifying with a single clip's latent_shape; dropped/duplicated rows during scheduling or attention masking; a stale latent_shape after changing resolution or frame count.","solutions":["Split the rows buffer per video (using the layout's block slices) and unpatchify each with its own latent_shape.","Ensure latent_shape's t,h,w exactly match the frames/resolution the rows were generated from.","Recompute latent_shape from the plan rather than caching it across requests."],"exampleFix":"# before\nlatent = minimax_h3_unpatchify_video_tokens(all_rows, latent_shape=one_clip_shape, patch_size=patch)\n\n# after\nfor sl, shape in zip(block_slices, block_latent_shapes):\n    latent_i = minimax_h3_unpatchify_video_tokens(all_rows[sl], latent_shape=shape, patch_size=patch)","handlingStrategy":"validation","validationCode":"t, h, w, _ = latent_shape\nrows_per_sample = t * h * w\nassert rows.shape[0] % rows_per_sample == 0, f\"row count {rows.shape[0]} not a multiple of {rows_per_sample}\"","typeGuard":"def rows_partition_cleanly(rows, latent_shape) -> bool:\n    t, h, w, _ = latent_shape\n    return rows.shape[0] % (t * h * w) == 0","tryCatchPattern":null,"preventionTips":["Unpatchify per video block using the layout's slices, not the concatenated buffer.","Derive latent_shape from the current plan/request rather than caching it."],"tags":["validation","tensor-shape","unpatchify","row-count","minimax-h3"],"backgroundTag":"tensor-dimension-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}