sgl-project/sglang · error · ValueError

(num_frames - 1) must be divisible by num_frame_per_block wh

Error message

(num_frames - 1) must be divisible by num_frame_per_block when independent_first_frame=True

What it means

When independent_first_frame=True and no image latents are provided, the first frame is a standalone block and the remaining t-1 frames must be divisible by num_frames_per_block; otherwise block tiling fails.

Source

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

                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
        with self.progress_bar(
            total=len(block_sizes) * len(timesteps), batch=batch
        ) as progress_bar:
            for current_num_frames in block_sizes:
                current_latents = latents[
                    :, :, start_index : start_index + current_num_frames, :, :
                ]

View on GitHub (pinned to 0132848349)

Solutions

  1. Use num_frames = 1 + k*num_frames_per_block (e.g. 1+4*25=101)
  2. Disable independent_first_frame if t is already a multiple of block size
  3. Round requested durations to whole blocks at the API boundary

Example fix

# before
req.num_frames = 100; independent_first_frame = True
# after
req.num_frames = 101; independent_first_frame = True  # 1 + 4*25
Defensive patterns

Strategy: validation

Validate before calling

assert (num_frames - 1) % num_frames_per_block == 0

Type guard

def frames_ok_independent(t: int, block: int) -> bool: return t >= 1 and (t - 1) % block == 0

Prevention

When it happens

Trigger: num_frames=49 with num_frames_per_block=25 and independent_first_frame=True → (49-1)%25 != 0 → error; correct counts look like 1 + k*num_frames_per_block.

Common situations: Using frame counts valid for the non-independent path (multiples of block size) after toggling independent_first_frame on; fps arithmetic rounding frames to non-conforming counts.

Related errors


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