sgl-project/sglang · error · ValueError

SD3 CLIP postprocessing requires hidden_states from encoder

Error message

SD3 CLIP postprocessing requires hidden_states from encoder output.

What it means

SD3 CLIP text postprocessing extracts the penultimate hidden_states layer (hidden_states[-2]) as the pre-final representation for Stable Diffusion 3. If the encoder was run with output_hidden_states=False (or a path that doesn't populate them), hidden_states is None and this ValueError fires.

Source

Thrown at python/sglang/multimodal_gen/configs/pipeline_configs/stablediffusion3.py:34

    CLIPTextConfig,
)
from sglang.multimodal_gen.configs.models.encoders.t5 import (
    T5ArchConfig,
    T5Config,
)
from sglang.multimodal_gen.configs.models.vaes.stablediffusion3 import (
    StableDiffusion3VAEConfig,
)
from sglang.multimodal_gen.configs.pipeline_configs.base import (
    ModelTaskType,
    SpatialImagePipelineConfig,
)


def sd3_clip_postprocess_text(outputs: BaseEncoderOutput, _text_inputs) -> torch.Tensor:
    """Extract pre-final hidden state for SD3 CLIP encoders."""
    if outputs.hidden_states is None:
        raise ValueError(
            "SD3 CLIP postprocessing requires hidden_states from encoder output."
        )
    return outputs.hidden_states[-2]


def t5_postprocess_text(outputs: BaseEncoderOutput, _text_inputs) -> torch.Tensor:
    return outputs.last_hidden_state


def select_sd3_vae_weight_files(
    safetensors_list: list[str],
    component_model_path: str,
    component_name: str,
    vae_precision: str,
) -> list[str]:
    """Select SD3 VAE checkpoint file candidates with minimal policy."""
    if component_name not in ("vae", "video_vae"):
        return safetensors_list

View on GitHub (pinned to 0132848349)

Solutions

  1. Re-run the CLIP encoder with output_hidden_states=True so outputs.hidden_states is populated
  2. If using a custom forward, return hidden_states from all layers (tuple), not just the last
  3. Pin/verify the transformers version and pass the flag through your encode helper

Example fix

# before
outputs = clip_encoder(input_ids, attention_mask=mask)  # hidden_states=None
emb = sd3_clip_postprocess_text(outputs, text_inputs)  # error

# after
outputs = clip_encoder(input_ids, attention_mask=mask, output_hidden_states=True)
emb = sd3_clip_postprocess_text(outputs, text_inputs)
Defensive patterns

Strategy: validation

Validate before calling

outputs = clip_encoder(input_ids, attention_mask=mask, output_hidden_states=True)
assert outputs.hidden_states is not None and len(outputs.hidden_states) >= 2

Type guard

def has_hidden_states(outputs) -> bool:
    return outputs.hidden_states is not None and len(outputs.hidden_states) >= 2

Try / catch

try:
    emb = sd3_clip_postprocess_text(outputs, text_inputs)
except ValueError:
    outputs = clip_encoder(input_ids, attention_mask=mask, output_hidden_states=True)
    emb = sd3_clip_postprocess_text(outputs, text_inputs)

Prevention

When it happens

Trigger: Calling sd3_clip_postprocess_text with an encoder output produced while output_hidden_states=False; swapping in a custom CLIP encoder wrapper that returns only pooler_output/last_hidden_state; transformers version behavior change where the flag isn't propagated.

Common situations: Upgrading transformers where hidden-state emission depends on an explicit flag; building a custom CLIPTextModel forward that discards hidden_states; memory optimizations that disabled hidden-state collection.

Related errors


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