{"record":{"id":"f0936db534866413","repo":"sgl-project/sglang","slug":"ltx-2-token-latents-seq-len-seq-len-is-not-divis","errorCode":null,"errorMessage":"LTX-2 token latents seq_len={seq_len} is not divisible by tokens_per_frame={tokens_per_frame}. Cannot time-shard for SP.","messagePattern":"LTX-2 token latents seq_len=(.+?) is not divisible by tokens_per_frame=(.+?)\\. Cannot time-shard for SP\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/configs/pipeline_configs/ltx_2.py","lineNumber":367,"sourceCode":"        if (latent_height % int(self.patch_size)) != 0 or (\n            latent_width % int(self.patch_size)\n        ) != 0:\n            raise ValueError(\n                \"Invalid spatial patching for packed token latents. Expected latent H/W \"\n                \"to be divisible by patch_size, got \"\n                f\"{latent_height=} {latent_width=} {self.patch_size=}.\"\n            )\n\n        post_patch_h = latent_height // int(self.patch_size)\n        post_patch_w = latent_width // int(self.patch_size)\n        tokens_per_frame = int(post_patch_h) * int(post_patch_w)\n        if tokens_per_frame <= 0:\n            raise ValueError(\n                f\"Invalid tokens_per_frame={tokens_per_frame} from \"\n                f\"{latent_height=} {latent_width=} {self.patch_size=}\"\n            )\n        if int(seq_len) % int(tokens_per_frame) != 0:\n            raise ValueError(\n                f\"LTX-2 token latents seq_len={seq_len} is not divisible by \"\n                f\"tokens_per_frame={tokens_per_frame}. Cannot time-shard for SP.\"\n            )\n        latent_num_frames = int(seq_len) // int(tokens_per_frame)\n        return int(latent_num_frames), int(tokens_per_frame)\n\n    def shard_latents_for_sp(self, batch, latents):\n        \"\"\"Shard LTX-2 packed token latents across SP ranks by latent time (frame) dimension.\"\"\"\n        sp_world_size = get_sp_world_size()\n        if sp_world_size <= 1:\n            return latents, False\n\n        # Default behavior for 5D latents.\n        if isinstance(latents, torch.Tensor) and latents.ndim == 5:\n            return super().shard_latents_for_sp(batch, latents)\n\n        # LTX-2 packed token latents [B, S, D]\n        if not (isinstance(latents, torch.Tensor) and latents.ndim == 3):","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/configs/pipeline_configs/ltx_2.py#L349-L385","documentation":"LTX-2 SP time-sharding splits packed token latents along the temporal axis, which requires seq_len to be an exact multiple of tokens_per_frame (one frame's token grid). If seq_len % tokens_per_frame != 0, the number of latent frames cannot be inferred and sharding is impossible. The message reports both values.","triggerScenarios":"Calling shard_latents_for_sp with a packed latent sequence whose length doesn't match whole frames — e.g. a batch mixing resolutions, seq_len from a different model's patching, or height/width in batch metadata inconsistent with the actual tensor shape.","commonSituations":"Feeding latents produced with a different patch_size or vae_scale_factor than the config declares; prompt-style (non-video) latents passed through the video path; batch metadata (height/width) disagreeing with the packed tensor's seq_len.","solutions":["Verify batch.height/batch.width in the request metadata exactly match the resolution used to produce the packed latents","Confirm config vae_scale_factor and patch_size match the values used at latent-encoding time","Check the packed tensor wasn't truncated/padded (e.g. by chunked prefill) so seq_len lost whole-frame alignment"],"exampleFix":"# before\n# latents encoded at 768x1280, but batch declares 512x512 -> seq_len mismatch\nbatch = VideoBatch(height=512, width=512, seq_len=latent_seq_len)\n\n# after\nbatch = VideoBatch(height=768, width=1280, seq_len=latent_seq_len)\nassert latent_seq_len % config.tokens_per_frame(batch) == 0","handlingStrategy":"validation","validationCode":"tpf = (batch.height // config.vae_scale_factor // config.patch_size) * (batch.width // config.vae_scale_factor // config.patch_size)\nassert int(seq_len) % tpf == 0, (seq_len, tpf, batch.height, batch.width)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep request metadata (height/width) in lockstep with the resolution used to encode latents","Never truncate/pad packed latents to non-multiple-of-frame lengths"],"tags":["ltx-2","video-generation","sequence-parallelism","tensor-shape-mismatch"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}