{"record":{"id":"98761ea8ff192751","repo":"sgl-project/sglang","slug":"invalid-spatial-patching-for-packed-token-latents","errorCode":null,"errorMessage":"Invalid spatial patching for packed token latents. Expected latent H/W to be divisible by patch_size, got {latent_height=} {latent_width=} {self.patch_size=}.","messagePattern":"Invalid spatial patching for packed token latents\\. Expected latent H/W to be divisible by patch_size, got (.+?) (.+?) (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/configs/pipeline_configs/ltx_2.py","lineNumber":352,"sourceCode":"            )\n        if int(seq_len) <= 0:\n            raise ValueError(f\"Expected {seq_len=} > 0 for packed token latents.\")\n        if int(self.vae_scale_factor) <= 0:\n            raise ValueError(f\"Invalid {self.vae_scale_factor=}. Must be > 0.\")\n        if int(self.patch_size) <= 0:\n            raise ValueError(f\"Invalid {self.patch_size=}. Must be > 0.\")\n\n        latent_height = int(batch.height) // int(self.vae_scale_factor)\n        latent_width = int(batch.width) // int(self.vae_scale_factor)\n        if latent_height <= 0 or latent_width <= 0:\n            raise ValueError(\n                \"Invalid latent H/W computed from batch.height/width: \"\n                f\"{batch.height=} {batch.width=} {self.vae_scale_factor=}\"\n            )\n        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            )","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/configs/pipeline_configs/ltx_2.py#L334-L370","documentation":"LTX-2 SP time-sharding requires latent height and width to be divisible by patch_size so each frame patches into an integer grid of tokens. This check fires when batch.height/vae_scale_factor or batch.width/vae_scale_factor is not a multiple of patch_size, which would otherwise produce a fractional token grid.","triggerScenarios":"Calling shard_latents_for_sp with a resolution whose latent dims aren't multiples of patch_size, e.g. height=500, patch_size=2, vae_scale_factor=8 gives latent_height=62 which is not divisible by 2.","commonSituations":"Arbitrary user-supplied resolutions not rounded to the model's required grid; feeding resolution from a video file's native dimensions without quantizing; mismatched patch_size between config and checkpoint.","solutions":["Round the request resolution to the nearest multiple of vae_scale_factor * patch_size (e.g. multiples of 16 for factor 8 and patch 2)","Use the model's documented native resolutions (e.g. 768x1280, 1280x720-aligned values)","Confirm patch_size in the config matches the checkpoint's transformer patch size"],"exampleFix":"# before\nbatch = VideoBatch(height=500, width=860)\nconfig.shard_latents_for_sp(batch)  # latent 62x107, not divisible by patch_size=2\n\n# after\nalign = config.vae_scale_factor * config.patch_size\nbatch = VideoBatch(height=round(500/align)*align, width=round(860/align)*align)\nconfig.shard_latents_for_sp(batch)","handlingStrategy":"validation","validationCode":"align = config.vae_scale_factor * config.patch_size\nassert batch.height % align == 0 and batch.width % align == 0, (batch.height, batch.width, align)\nbatch = batch.evolve(height=round(batch.height/align)*align, width=round(batch.width/align)*align)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Snap user resolutions to multiples of vae_scale_factor*patch_size before scheduling","Expose the alignment requirement in your request API so clients pre-quantize"],"tags":["ltx-2","video-generation","resolution-validation","divisibility"],"backgroundTag":"dimension-divisibility-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}