sgl-project/sglang · error · ValueError

num_frames must be divisible by num_frames_per_block for cau

Error message

num_frames must be divisible by num_frames_per_block for causal DMD denoising

What it means

In causal DMD denoising forward, when the first frame is not independent (or image conditioning latents are present), total frame count t must be divisible by num_frames_per_block so blocks tile evenly.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/causal_denoising.py:1242

                    crossattn_cache=self.crossattn_cache,
                    current_start_frame=current_start_frame,
                    image_kwargs=image_kwargs,
                    pos_cond_kwargs=pos_cond_kwargs,
                    target_dtype=target_dtype,
                    autocast_enabled=autocast_enabled,
                )
                current_start_frame += block
                remaining_frames -= block

        # Base position offset from any cache warm-up
        pos_start_base = current_start_frame

        # Determine block sizes
        if not independent_first_frame or (
            independent_first_frame and batch.image_latent is not None
        ):
            if t % self.num_frames_per_block != 0:
                raise ValueError(
                    "num_frames must be divisible by num_frames_per_block for causal DMD denoising"
                )
            num_blocks = t // self.num_frames_per_block
            block_sizes = [self.num_frames_per_block] * num_blocks
            start_index = 0
        else:
            if (t - 1) % self.num_frames_per_block != 0:
                raise ValueError(
                    "(num_frames - 1) must be divisible by num_frame_per_block when independent_first_frame=True"
                )
            num_blocks = (t - 1) // self.num_frames_per_block
            block_sizes = [1] + [self.num_frames_per_block] * num_blocks
            start_index = 0

        def prepare_context_input(current_latents):
            return current_latents

        # DMD loop in causal blocks

View on GitHub (pinned to 0132848349)

Solutions

  1. Set num_frames to a multiple of num_frames_per_block
  2. Adjust num_frames_per_block to a divisor of your frame count
  3. Enable independent_first_frame (and no image conditioning) so (t-1) must be divisible instead

Example fix

# before
req.num_frames = 50  # block=25
# after
req.num_frames = 50; req.num_frames_per_block = 25  # ok; or use 48 with block 24
Defensive patterns

Strategy: validation

Validate before calling

assert num_frames % num_frames_per_block == 0

Type guard

def frames_ok(t: int, block: int, indep: bool, has_img: bool) -> bool:
    return (t - 1) % block == 0 if (indep and not has_img) else t % block == 0

Prevention

When it happens

Trigger: num_frames=100 with num_frames_per_block=25 fails (100%25==0 passes); e.g. num_frames=50 with block 24 → ValueError during forward.

Common situations: Requesting arbitrary clip lengths (e.g. 4.1s at 24fps); block size from model config (e.g. 25 for 1s@25fps) mismatched with requested frames; image-to-video paths that include the conditioned frame in t.

Related errors


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