{"record":{"id":"979043de3b6ae601","repo":"sgl-project/sglang","slug":"num-frames-1-must-be-divisible-by-num-frame-pe","errorCode":null,"errorMessage":"(num_frames - 1) must be divisible by num_frame_per_block when independent_first_frame=True","messagePattern":"\\(num_frames - 1\\) must be divisible by num_frame_per_block when independent_first_frame=True","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/causal_denoising.py","lineNumber":1250,"sourceCode":"                remaining_frames -= block\n\n        # Base position offset from any cache warm-up\n        pos_start_base = current_start_frame\n\n        # Determine block sizes\n        if not independent_first_frame or (\n            independent_first_frame and batch.image_latent is not None\n        ):\n            if t % self.num_frames_per_block != 0:\n                raise ValueError(\n                    \"num_frames must be divisible by num_frames_per_block for causal DMD denoising\"\n                )\n            num_blocks = t // self.num_frames_per_block\n            block_sizes = [self.num_frames_per_block] * num_blocks\n            start_index = 0\n        else:\n            if (t - 1) % self.num_frames_per_block != 0:\n                raise ValueError(\n                    \"(num_frames - 1) must be divisible by num_frame_per_block when independent_first_frame=True\"\n                )\n            num_blocks = (t - 1) // self.num_frames_per_block\n            block_sizes = [1] + [self.num_frames_per_block] * num_blocks\n            start_index = 0\n\n        def prepare_context_input(current_latents):\n            return current_latents\n\n        # DMD loop in causal blocks\n        with self.progress_bar(\n            total=len(block_sizes) * len(timesteps), batch=batch\n        ) as progress_bar:\n            for current_num_frames in block_sizes:\n                current_latents = latents[\n                    :, :, start_index : start_index + current_num_frames, :, :\n                ]\n","sourceCodeStart":1232,"sourceCodeEnd":1268,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/causal_denoising.py#L1232-L1268","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use num_frames = 1 + k*num_frames_per_block (e.g. 1+4*25=101)","Disable independent_first_frame if t is already a multiple of block size","Round requested durations to whole blocks at the API boundary"],"exampleFix":"# before\nreq.num_frames = 100; independent_first_frame = True\n# after\nreq.num_frames = 101; independent_first_frame = True  # 1 + 4*25","handlingStrategy":"validation","validationCode":"assert (num_frames - 1) % num_frames_per_block == 0","typeGuard":"def frames_ok_independent(t: int, block: int) -> bool: return t >= 1 and (t - 1) % block == 0","tryCatchPattern":null,"preventionTips":["Use num_frames = 1 + k*block for independent-first-frame models","Round user-supplied seconds to nearest valid block count"],"tags":["causal-denoising","frame-count","divisibility"],"backgroundTag":"divisibility-constraint-violated","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}