sgl-project/sglang · error · ValueError

The native SD2 UNet currently supports only the Hunyuan3D fo

Error message

The native SD2 UNet currently supports only the Hunyuan3D four-level SD2.1 block layout.

What it means

The native SD2 UNet implementation only supports the exact Hunyuan3D-style SD2.1 architecture: a fixed four-level down/up block layout (DownBlock2D + 3 CrossAttnDownBlock2D; UpBlock2D + 3 CrossAttnUpBlock2D). Any other block layout fails config validation.

Source

Thrown at python/sglang/multimodal_gen/runtime/models/dits/stable_diffusion.py:88

        )
        parsed.validate()
        return parsed

    def validate(self) -> None:
        expected_down = (
            "CrossAttnDownBlock2D",
            "CrossAttnDownBlock2D",
            "CrossAttnDownBlock2D",
            "DownBlock2D",
        )
        expected_up = (
            "UpBlock2D",
            "CrossAttnUpBlock2D",
            "CrossAttnUpBlock2D",
            "CrossAttnUpBlock2D",
        )
        if self.down_block_types != expected_down or self.up_block_types != expected_up:
            raise ValueError(
                "The native SD2 UNet currently supports only the Hunyuan3D "
                "four-level SD2.1 block layout."
            )
        if len(self.block_out_channels) != 4 or len(self.attention_head_dim) != 4:
            raise ValueError("Hunyuan3D SD2.1 UNet requires four channel stages.")
        if self.layers_per_block != 2 or self.transformer_layers_per_block != 1:
            raise ValueError(
                "Hunyuan3D SD2.1 UNet requires two ResNet layers and one "
                "transformer layer per block."
            )
        if not self.use_linear_projection:
            raise ValueError("Hunyuan3D SD2.1 checkpoints require linear projection.")


@dataclass
class StableDiffusionUNetOutput:
    sample: torch.Tensor

View on GitHub (pinned to 0132848349)

Solutions

  1. Use the Hunyuan3D SD2.1 UNet config: down_block_types=(DownBlock2D, CrossAttnDownBlock2D x3), up_block_types=(UpBlock2D, CrossAttnUpBlock2D x3)
  2. For non-Hunyuan3D SD2 checkpoints, use diffusers' UNet2DConditionModel instead of this native path
  3. Verify block_out_channels and attention_head_dim both have 4 entries and layers_per_block=2

Example fix

# before
cfg.down_block_types = ["CrossAttnDownBlock2D"] * 4
# after
cfg.down_block_types = ["DownBlock2D", "CrossAttnDownBlock2D", "CrossAttnDownBlock2D", "CrossAttnDownBlock2D"]
cfg.up_block_types = ["UpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D"]
Defensive patterns

Strategy: validation

Validate before calling

EXPECTED_DOWN = ("DownBlock2D", "CrossAttnDownBlock2D", "CrossAttnDownBlock2D", "CrossAttnDownBlock2D")
EXPECTED_UP = ("UpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D")
assert tuple(cfg.down_block_types) == EXPECTED_DOWN and tuple(cfg.up_block_types) == EXPECTED_UP

Type guard

def is_hunyuan3d_sd2_layout(cfg) -> bool:
    return (tuple(cfg.down_block_types) == ("DownBlock2D", "CrossAttnDownBlock2D", "CrossAttnDownBlock2D", "CrossAttnDownBlock2D")
            and tuple(cfg.up_block_types) == ("UpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D"))

Prevention

When it happens

Trigger: Loading a UNet config (e.g. via from_dict) whose down_block_types/up_block_types deviate from the Hunyuan3D SD2.1 layout — different depth, mid-block-only variants, or vanilla SD configs with reordered blocks.

Common situations: Pointing the loader at a vanilla Stable Diffusion 2 config or a community fine-tune with modified block types; version drift where config JSON keys were renamed and defaults fell back to a mismatched layout.

Related errors


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