sgl-project/sglang · error · TypeError

Expected BasicTransformerBlock, got {type(transformer).__nam

Error message

Expected BasicTransformerBlock, got {type(transformer).__name__}.

What it means

During _replace_transformer_blocks, the replace() helper expects the first transformer block of each attention module to be a diffusers BasicTransformerBlock so it can wrap it into a Hunyuan3DPaintTransformerBlock. If the checkpoint/module already uses a different block type, a TypeError is raised.

Source

Thrown at python/sglang/multimodal_gen/runtime/models/dits/hunyuan3d_paint.py:168

            encoder_hidden_states=encoder_hidden_states,
            attention_mask=encoder_attention_mask,
        )
        return hidden_states + self.transformer.ff(
            self.transformer.norm3(hidden_states)
        )


def _replace_transformer_blocks(
    unet: StableDiffusionUNet2DConditionModel,
    *,
    use_multiview_attention: bool,
    use_reference_attention: bool,
    is_turbo: bool,
) -> None:
    def replace(model: Transformer2DModel, layer_name: str) -> None:
        transformer = model.transformer_blocks[0]
        if not isinstance(transformer, BasicTransformerBlock):
            raise TypeError(
                f"Expected BasicTransformerBlock, got {type(transformer).__name__}."
            )
        model.transformer_blocks[0] = Hunyuan3DPaintTransformerBlock(
            transformer,
            layer_name,
            use_multiview_attention=use_multiview_attention,
            use_reference_attention=use_reference_attention,
            is_turbo=is_turbo,
        )

    for block_index, block in enumerate(unet.down_blocks):
        if not isinstance(block, CrossAttnDownBlock2D):
            continue
        for attention_index, attention in enumerate(block.attentions):
            replace(attention, f"down_{block_index}_{attention_index}_0")

    mid_block = unet.mid_block
    if not isinstance(mid_block, UNetMidBlock2DCrossAttn):

View on GitHub (pinned to 0132848349)

Solutions

  1. Use the diffusers version this code was developed against (check the repo's requirements/pin)
  2. Make sure you call _replace_transformer_blocks only once per UNet
  3. Verify you are loading the expected SD2.x UNet architecture, not a custom variant

Example fix

# before
_replace_transformer_blocks(custom_unet, ...)  # custom blocks

# after
unet = UNet2DConditionModel.from_pretrained("stabilityai/stable-diffusion-2-1", subfolder="unet")
_replace_transformer_blocks(unet, ...)
Defensive patterns

Strategy: type-guard

Validate before calling

from diffusers.models.transformers.transformer_2d import BasicTransformerBlock
assert isinstance(model.transformer_blocks[0], BasicTransformerBlock), type(model.transformer_blocks[0])

Type guard

def is_basic_transformer_block(model) -> bool:
    from diffusers.models.transformers.transformer_2d import BasicTransformerBlock
    return isinstance(model.transformer_blocks[0], BasicTransformerBlock)

Prevention

When it happens

Trigger: Calling _replace_transformer_blocks on a UNet whose attentions' transformer_blocks[0] is not BasicTransformerBlock — e.g. a custom/different diffusers version's block class, an already-replaced block, or a non-SD2 UNet.

Common situations: diffusers version drift changing the block class; running the replacement twice on the same UNet; using a UNet architecture other than the expected Stable Diffusion 2.x one.

Related errors


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