sgl-project/sglang · error · ValueError

video rows must be divisible by t*h*w for latent_shape=

Error message

video rows {int(rows.shape[0])} must be divisible by t*h*w {rows_per_sample} for latent_shape={list(latent_shape)}

What it means

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.

Solutions

  1. Split the rows buffer per video (using the layout's block slices) and unpatchify each with its own latent_shape.
  2. Ensure latent_shape's t,h,w exactly match the frames/resolution the rows were generated from.
  3. Recompute latent_shape from the plan rather than caching it across requests.

Example fix

# before
latent = minimax_h3_unpatchify_video_tokens(all_rows, latent_shape=one_clip_shape, patch_size=patch)

# after
for sl, shape in zip(block_slices, block_latent_shapes):
    latent_i = minimax_h3_unpatchify_video_tokens(all_rows[sl], latent_shape=shape, patch_size=patch)
Defensive patterns

Strategy: validation

Validate before calling

t, h, w, _ = latent_shape
rows_per_sample = t * h * w
assert rows.shape[0] % rows_per_sample == 0, f"row count {rows.shape[0]} not a multiple of {rows_per_sample}"

Type guard

def rows_partition_cleanly(rows, latent_shape) -> bool:
    t, h, w, _ = latent_shape
    return rows.shape[0] % (t * h * w) == 0

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

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

    *,
    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)
    t, h, w, channel = _int_tuple(latent_shape, "latent_shape", 4)
    pt, ph, pw = _int_tuple(patch_size, "patch_size", 3)
    expected_dim = pt * ph * pw * channel
    if int(rows.shape[-1]) != expected_dim:
        raise ValueError(
            f"video token dim {int(rows.shape[-1])} != patch volume * channel "
            f"{expected_dim} for latent_shape={list(latent_shape)}, "
            f"patch_size={[pt, ph, pw]}"
        )
    rows_per_sample = t * h * w
    if int(rows.shape[0]) % rows_per_sample:
        raise ValueError(
            f"video rows {int(rows.shape[0])} must be divisible by t*h*w "
            f"{rows_per_sample} for latent_shape={list(latent_shape)}"
        )
    packed = rows.reshape(-1, t, h, w, channel, pt, ph, pw)
    latent = torch.einsum("nthwcrpq->nctrhpwq", packed)
    return latent.reshape(-1, channel, t * pt, h * ph, w * pw).contiguous()


def minimax_h3_unpack_audio_tokens(
    rows: torch.Tensor,
    *,
    audio_t: int,
    audio_channel: int,
) -> torch.Tensor:
    """Unpack DiT audio token rows into SGLang audio VAE latent [C,latent_dim,T]."""

    _rank(rows, "audio token rows", 2)
    audio_t = int(audio_t)

View on GitHub (pinned to 0132848349)