sgl-project/sglang · error · ValueError

Qwen-Image-Layered generated latent shapes must match, got {

Error message

Qwen-Image-Layered generated latent shapes must match, got {generated_shapes}.

What it means

Layered Qwen-Image generation unpacks latents assuming every layer was generated at the same resolution. If the per-layer generated latent shapes in batch.img_shapes differ (mixed resolutions/aspect ratios across layers), the stack/unpack would be ragged, so it raises listing the offending shapes.

Source

Thrown at python/sglang/multimodal_gen/configs/pipeline_configs/qwen_image.py:824

        cond_kwargs = {
            "txt_seq_lens": txt_seq_lens,
            "img_shapes": img_shapes,
            "freqs_cis": (img_cache, txt_cache),
            "additional_t_cond": torch.tensor([0], device=device, dtype=torch.long),
            "encoder_hidden_states_mask": encoder_hidden_states_mask,
        }
        return cond_kwargs

    def _unpad_and_unpack_latents(self, latents, batch):
        channels = self.dit_config.arch_config.in_channels
        batch_size = latents.shape[0]

        img_shapes = batch.img_shapes
        generated_shapes = img_shapes[0][:-1] if img_shapes and img_shapes[0] else []
        if not generated_shapes:
            raise ValueError("Qwen-Image-Layered requires generated latent shapes.")
        if len({tuple(shape) for shape in generated_shapes}) != 1:
            raise ValueError(
                "Qwen-Image-Layered generated latent shapes must match, got "
                f"{generated_shapes}."
            )
        layers = len(generated_shapes)
        _, latent_height, latent_width = generated_shapes[0]
        height = 2 * int(latent_height)
        width = 2 * int(latent_width)

        latents = maybe_unpad_latents(latents, batch)
        latents = latents.view(
            batch_size, layers, height // 2, width // 2, channels // 4, 2, 2
        )
        latents = latents.permute(0, 1, 4, 2, 5, 3, 6)

        latents = latents.reshape(
            batch_size, layers, channels // (2 * 2), height, width
        )
        latents = latents.permute(0, 2, 1, 3, 4)  # (b, c, f, h, w)

View on GitHub (pinned to 0132848349)

Solutions

  1. Force all layers to a single shared resolution before building the layered batch
  2. When merging separately generated layers, resize/pad all latents to one shape first (or regenerate at a common size)
  3. Validate shapes client-side: len({tuple(s) for s in generated_shapes}) == 1 before submitting

Example fix

# before
layer_shapes = [(4, 128, 128), (4, 96, 160)]  # mismatched

# after
layer_shapes = [(4, 128, 128), (4, 128, 128)]  # all layers same latent shape
Defensive patterns

Strategy: validation

Validate before calling

generated = [tuple(s) for s in (batch.img_shapes[0][:-1] if batch.img_shapes else [])]
assert generated and len(set(generated)) == 1, f"layer shapes differ: {generated}"

Type guard

def layers_uniform(batch) -> bool:
    shapes = {tuple(s) for s in (batch.img_shapes[0][:-1] if batch.img_shapes and batch.img_shapes[0] else [])}
    return len(shapes) == 1

Prevention

When it happens

Trigger: Constructing a layered request where different layers have different height/width (e.g. layer 1 at 1024x1024, layer 2 at 768x512); code that sets per-layer img_shapes from user-supplied heterogeneous sizes.

Common situations: UI letting users pick per-layer resolution; porting old code that generated layers in separate calls at different sizes and then merging them into one batch; aspect-ratio normalization applied to only some layers.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/7f26e06bf04ebc1b. Report an issue: GitHub.