sgl-project/sglang · error · AttributeError

Unsupported text encoder output: expected `hidden_states`.

Error message

Unsupported text encoder output: expected `hidden_states`.

What it means

LTX-2's _gemma_postprocess_func expects the text-encoder output object to expose hidden_states (with the expected shape/layout); if the output structure lacks it, this AttributeError is raised because the pipeline cannot extract token embeddings.

Source

Thrown at python/sglang/multimodal_gen/configs/pipeline_configs/ltx_2.py:167

def _gemma_postprocess_func(
    outputs: BaseEncoderOutput,
    text_inputs: dict,
    pipeline_config: Optional["LTX2PipelineConfig"] = None,
) -> torch.Tensor:
    # LTX-2 requires all hidden states concatenated for the connector
    if hasattr(outputs, "hidden_states") and outputs.hidden_states is not None:
        hidden_states = torch.stack(outputs.hidden_states, dim=-1)
        attention_mask = text_inputs["attention_mask"]
        if (
            pipeline_config is not None
            and pipeline_config.dit_config.arch_config.caption_proj_before_connector
        ):
            return pack_text_embeds_v2(hidden_states, attention_mask)

        sequence_lengths = attention_mask.sum(dim=-1)
        return pack_text_embeds(hidden_states, sequence_lengths, padding_side="left")
    else:
        raise AttributeError(
            "Unsupported text encoder output: expected `hidden_states`."
        )


@dataclasses.dataclass
class LTX2PipelineConfig(PipelineConfig):
    """Configuration for LTX-Video pipeline."""

    task_type: ModelTaskType = ModelTaskType.TI2V
    skip_input_image_preprocess: bool = True
    generator_device: str = "cpu"
    dit_config: LTX2Config = field(default_factory=LTX2Config)

    # Distilled checkpoints are trained against one fixed sigma schedule rather
    # than a step count. When set, it replaces the derived schedule.
    default_sigmas: tuple[float, ...] | None = None

    # Model architecture

View on GitHub (pinned to 0132848349)

Solutions

  1. Ensure the text encoder output exposes hidden_states (e.g. BaseModelOutputWithPast from HF transformers)
  2. If using a custom encoder, wrap its output: return BaseModelOutputWithPast(hidden_states=...) or add a hidden_states property
  3. In tests/mocks, return an object with a real hidden_states attribute matching [batch, seq, hidden]

Example fix

# before
class FakeEncoder(nn.Module):
    def forward(self, ids):
        return self.backbone(ids)  # tuple, no .hidden_states

# after
from transformers.modeling_outputs import BaseModelOutputWithPast
class FakeEncoder(nn.Module):
    def forward(self, ids):
        out = self.backbone(ids)
        return BaseModelOutputWithPast(hidden_states=out[0])
Defensive patterns

Strategy: fallback

Validate before calling

out = text_encoder(input_ids)
if not hasattr(out, "hidden_states"):
    out = wrap_as_model_output(out)  # expose .hidden_states

Type guard

def has_hidden_states(out) -> bool:
    return hasattr(out, "hidden_states") and out.hidden_states is not None

Try / catch

except AttributeError as e:
    if "hidden_states" in str(e):
        hs = encoder_out[0] if isinstance(encoder_out, (tuple, list)) else encoder_out
        out = BaseModelOutputWithPast(hidden_states=hs)

Prevention

When it happens

Trigger: Swapping the text encoder (or a mock/fake encoder in tests) whose forward returns an object without a hidden_states attribute — e.g. returns a plain tensor, a tuple, or a dataclass with last_hidden_state instead of hidden_states.

Common situations: Running tests with stub encoders; upgrading/changing transformers versions where output dataclass field names differ; plugging a custom T5/Gemma-compatible encoder with a different output schema.

Related errors


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