sgl-project/sglang · error · ValueError

The Hunyuan3D SD2.1 UNet has no added conditioning.

Error message

The Hunyuan3D SD2.1 UNet has no added conditioning.

What it means

Raised by the Hunyuan3D SD2.1 UNet forward when timestep_cond or added_cond_kwargs is not None. This UNet architecture has no added-conditioning pathway (unlike SDXL/SD3 which take text embeddings as added cond), so passing them is a caller bug.

Source

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

    def forward(
        self,
        sample: torch.Tensor,
        timestep: torch.Tensor | float | int,
        encoder_hidden_states: torch.Tensor,
        class_labels: torch.Tensor | None = None,
        timestep_cond: torch.Tensor | None = None,
        attention_mask: torch.Tensor | None = None,
        cross_attention_kwargs: dict[str, Any] | None = None,
        added_cond_kwargs: dict[str, torch.Tensor] | None = None,
        down_block_additional_residuals: tuple[torch.Tensor, ...] | None = None,
        mid_block_additional_residual: torch.Tensor | None = None,
        down_intrablock_additional_residuals: tuple[torch.Tensor, ...] | None = None,
        encoder_attention_mask: torch.Tensor | None = None,
        return_dict: bool = True,
    ) -> StableDiffusionUNetOutput | tuple[torch.Tensor]:
        if timestep_cond is not None or added_cond_kwargs is not None:
            raise ValueError("The Hunyuan3D SD2.1 UNet has no added conditioning.")
        if down_intrablock_additional_residuals is not None:
            raise ValueError("T2I adapter residuals are not supported by Hunyuan3D.")
        if (down_block_additional_residuals is None) != (
            mid_block_additional_residual is None
        ):
            raise ValueError(
                "ControlNet down and mid residuals must be provided together."
            )

        attention_mask = self._attention_bias(attention_mask, sample.dtype)
        encoder_attention_mask = self._attention_bias(
            encoder_attention_mask, sample.dtype
        )
        if self.config.center_input_sample:
            sample = 2 * sample - 1.0

        time_embedding = self._time_embedding(sample, timestep)
        if self.class_embedding is not None:

View on GitHub (pinned to 0132848349)

Solutions

  1. Remove timestep_cond and added_cond_kwargs from the forward call
  2. Pass conditioning through encoder_hidden_states / class_labels instead

Example fix

# before
unet(latents, t, encoder_hidden_states=ctx, added_cond_kwargs=cond)
# after
unet(latents, t, encoder_hidden_states=ctx)
Defensive patterns

Strategy: validation

Validate before calling

assert timestep_cond is None and added_cond_kwargs is None before calling this UNet

Type guard

def has_no_added_cond(timestep_cond, added_cond_kwargs) -> bool:
    return timestep_cond is None and added_cond_kwargs is None

Prevention

When it happens

Trigger: Forwarding diffusers-style SDXL arguments (timestep_cond, added_cond_kwargs={'text_embeds':..., 'time_ids':...}) into this SD2.1 UNet.

Common situations: Reusing pipeline glue code written for SDXL or another UNet that supports added conditioning.

Related errors


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