{"record":{"id":"a25e9aff96c49248","repo":"sgl-project/sglang","slug":"sana-wm-height-width-must-be-divisible-by-the-ltx","errorCode":null,"errorMessage":"SANA-WM height/width must be divisible by the LTX-2 spatial stride ({h_stride}, {w_stride}); got height={batch.height}, width={batch.width}.","messagePattern":"SANA-WM height/width must be divisible by the LTX-2 spatial stride \\((.+?), (.+?)\\); got height=(.+?), width=(.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/configs/pipeline_configs/sana_wm.py","lineNumber":181,"sourceCode":"        return ModelDeploymentConfig(\n            dit_layerwise_offload_modes=(\"memory\",),\n            # Conservative auto-FSDP gate for the 720p world-model path. Users\n            # can still force FSDP explicitly on smaller cards.\n            fsdp_auto_min_available_memory_gb=60,\n        )\n\n    # --- Latent shape ---\n    def prepare_latent_shape(self, batch, batch_size: int, num_frames: int):\n        \"\"\"\n        Returns 5D latent shape: (B, 128, T_latent, H_sp, W_sp).\n        T_latent = ceil((num_frames - 1) / temporal_stride) + 1\n        \"\"\"\n        t_stride = self.vae_stride[0]\n        h_stride = self.vae_stride[1]\n        w_stride = self.vae_stride[2] if len(self.vae_stride) > 2 else h_stride\n\n        if batch.height % h_stride != 0 or batch.width % w_stride != 0:\n            raise ValueError(\n                \"SANA-WM height/width must be divisible by the LTX-2 spatial \"\n                f\"stride ({h_stride}, {w_stride}); got \"\n                f\"height={batch.height}, width={batch.width}.\"\n            )\n\n        T_latent = (num_frames - 1) // t_stride + 1\n        H_sp = batch.height // h_stride\n        W_sp = batch.width // w_stride\n        z_dim = self.vae_config.arch_config.latent_channels  # 128\n\n        return (batch_size, z_dim, T_latent, H_sp, W_sp)\n\n    def adjust_num_frames(self, num_frames: int) -> int:\n        \"\"\"Ensure (num_frames - 1) is divisible by VAE temporal stride.\"\"\"\n        t_stride = self.vae_stride[0]\n        if (num_frames - 1) % t_stride != 0:\n            adjusted = ((num_frames - 1) // t_stride) * t_stride + 1\n            logger.warning(","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/configs/pipeline_configs/sana_wm.py#L163-L199","documentation":"SANA-WM's latent shape preparation requires spatial dimensions divisible by the LTX-2 VAE strides. If batch.height or batch.width isn't a multiple of the respective stride, latent dims wouldn't be integers, so prepare_latent_shape rejects the request with the exact strides and offending dimensions.","triggerScenarios":"Requesting video/image generation with height/width like 1000 (not divisible by a stride of e.g. 32), or odd sizes from arbitrary user input; mixing up the stride order when setting vae_stride.","commonSituations":"Free-form resolution fields in a UI; upscaling/scaling math producing non-multiple sizes; assuming any even number works when the LTX-2 VAE needs multiples of 32/64.","solutions":["Round height/width to the nearest multiple of the stride: h = round(h / h_stride) * h_stride","Print/inspect self.vae_stride and ensure both dimensions satisfy h % h_stride == 0 and w % w_stride == 0","Snap user input at the API boundary rather than letting raw values through"],"exampleFix":"# before\npipe(height=1000, width=700)  # 1000 % 32 == 16 -> error\n\n# after\nh_stride, w_stride = 32, 32\npipe(height=round(1000/h_stride)*h_stride, width=round(700/w_stride)*w_stride)  # 992x704","handlingStrategy":"validation","validationCode":"h_stride, w_stride = pipe.vae_stride[1], pipe.vae_stride[2] if len(pipe.vae_stride) > 2 else pipe.vae_stride[1]\nif batch.height % h_stride or batch.width % w_stride:\n    batch.height = round(batch.height / h_stride) * h_stride\n    batch.width = round(batch.width / w_stride) * w_stride","typeGuard":null,"tryCatchPattern":"try:\n    latent_shape = pipe.prepare_latent_shape(batch, batch_size, num_frames)\nexcept ValueError as e:\n    if \"divisible by\" in str(e):\n        batch.height = round(batch.height / h_stride) * h_stride\n        batch.width = round(batch.width / w_stride) * w_stride\n        latent_shape = pipe.prepare_latent_shape(batch, batch_size, num_frames)\n    else:\n        raise","preventionTips":["Snap all user-supplied resolutions to VAE stride multiples at the API boundary","Read vae_stride from the config rather than hardcoding"],"tags":["sana-wm","vae-stride","resolution-validation","video-generation"],"backgroundTag":"dimension-not-divisible-by-stride","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}