{"record":{"id":"099492c861ebb286","repo":"sgl-project/sglang","slug":"cannot-duplicate-image-of-batch-size-image-late","errorCode":null,"errorMessage":"Cannot duplicate `image` of batch size {image_latents.shape[0]} to {batch_size} text prompts.","messagePattern":"Cannot duplicate `image` of batch size (.+?) to (.+?) text prompts\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/qwen_image_layered.py","lineNumber":445,"sourceCode":"            image = align_tensor_to_module_dtype(image, self.vae, device=device)\n            if image.shape[1] != self.latent_channels:\n                image_latents = self._encode_vae_image(image=image, generator=generator)\n            else:\n                image_latents = image\n            if (\n                batch_size > image_latents.shape[0]\n                and batch_size % image_latents.shape[0] == 0\n            ):\n                # expand init_latents for batch_size\n                additional_image_per_prompt = batch_size // image_latents.shape[0]\n                image_latents = torch.cat(\n                    [image_latents] * additional_image_per_prompt, dim=0\n                )\n            elif (\n                batch_size > image_latents.shape[0]\n                and batch_size % image_latents.shape[0] != 0\n            ):\n                raise ValueError(\n                    f\"Cannot duplicate `image` of batch size {image_latents.shape[0]} to {batch_size} text prompts.\"\n                )\n            else:\n                image_latents = torch.cat([image_latents], dim=0)\n\n            image_latent_height, image_latent_width = image_latents.shape[3:]\n            image_latents = image_latents.permute(\n                0, 2, 1, 3, 4\n            )  # (b, c, f, h, w) -> (b, f, c, h, w)\n            image_latents = self._pack_latents(\n                image_latents,\n                batch_size,\n                num_channels_latents,\n                image_latent_height,\n                image_latent_width,\n                1,\n            )\n","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/qwen_image_layered.py#L427-L463","documentation":"In prepare_latents, when image latents are provided for image editing/generation, the number of latent batches must either match the number of text prompts or divide it evenly so latents can be duplicated via repeat/repeat_interleave. If batch_size > image_latents.shape[0] and batch_size % image_latents.shape[0] != 0, duplication is impossible and the error is raised.","triggerScenarios":"Passing one reference image (image_latents batch 1) with 3 text prompts (batch_size 3), or 2 images with 5 prompts — any non-divisible combination where prompts outnumber latents.","commonSituations":"Prompt expansion (e.g. cfg or multiple variants per prompt) multiplying batch_size to a number not divisible by the number of input images; mixing batched prompts with a single image incorrectly; off-by-one in prompt list construction.","solutions":["Make batch_size divisible by image_latents.shape[0]: pass one image per prompt (repeat the image path list to match prompt count) or adjust the prompt list length.","Check batch_size = num_prompts * num_variants before the call and tile images accordingly.","Ensure you are not unintentionally duplicating only some prompts."],"exampleFix":"# before\nprompts = [\"edit a\", \"edit b\", \"edit c\"]\nimage_path = [\"img.png\"]  # 1 latent vs 3 prompts\n\n# after\nimage_path = [\"img.png\", \"img.png\", \"img.png\"]  # or reduce to 1 prompt","handlingStrategy":"validation","validationCode":"n_lat = image_latents.shape[0] if image_latents is not None else None\nif n_lat is not None:\n    assert batch_size % n_lat == 0, f\"batch {batch_size} not divisible by {n_lat} images\"","typeGuard":"def batch_divides_latents(batch_size: int, image_latents) -> bool:\n    return image_latents is None or batch_size == image_latents.shape[0] or batch_size % image_latents.shape[0] == 0","tryCatchPattern":null,"preventionTips":["Compute effective batch (prompts x variants) before tiling images.","Repeat the image list with image_paths * len(prompts) when editing every prompt with the same image."],"tags":["qwen-image","diffusers","batch-size","latents","image-editing"],"backgroundTag":"batch-size-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}