sgl-project/sglang · error · ValueError

Qwen-Image-Layered requires generated latent shapes.

Error message

Qwen-Image-Layered requires generated latent shapes.

What it means

The Qwen-Image-Layered variant needs the per-layer generated latent shapes from batch.img_shapes to unpad and unpack latents into layers. If img_shapes is empty or its first entry carries no generated shapes (only e.g. a final shape), _unpad_and_unpack_latents cannot proceed and raises.

Source

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

        ).to(device=device)

        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

View on GitHub (pinned to 0132848349)

Solutions

  1. Use the Qwen-Image-Layered pipeline end-to-end so prepare/encode steps populate batch.img_shapes with per-layer generated shapes
  2. Verify batch.img_shapes is a non-empty nested list where each entry has [generated_shape..., final_shape]; fix serialization if it flattens it
  3. Rebuild the batch via the layered pipeline's prep path before post_denoising_loop

Example fix

# before
latents = pipe.post_denoising_loop(batch_without_img_shapes)

# after
batch = pipe.prepare_batch(...)  # layered pipeline populates batch.img_shapes
latents = pipe.post_denoising_loop(batch)
Defensive patterns

Strategy: validation

Validate before calling

shapes = batch.img_shapes[0][:-1] if batch.img_shapes and batch.img_shapes[0] else []
assert shapes, "Layered pipeline requires populated batch.img_shapes with per-layer generated shapes"

Type guard

def is_layered_batch(batch) -> bool:
    return bool(batch.img_shapes) and len(batch.img_shapes[0]) > 1

Prevention

When it happens

Trigger: Running the layered pipeline on a batch where img_shapes was never populated or img_shapes[0][:-1] is empty — typically because a non-layered QwenImage path built the batch, or img_shapes was stripped/serialized incorrectly.

Common situations: Reusing a batch object constructed for plain QwenImage with the Layered config; downstream code (scheduler, serialization) dropping the nested img_shapes field; calling post_denoising_loop manually without going through prepare_latents that records shapes.

Related errors


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