sgl-project/sglang · error · ValueError

The `hidden_states` sequence length {hidden_states.shape[1]}

Error message

The `hidden_states` sequence length {hidden_states.shape[1]} should be divisible by the number of learnable registers {self.num_learnable_registers}

What it means

ValueError from LTX-2 connector forward: when learnable_registers is enabled, hidden_states seq_len must be divisible by num_learnable_registers because the registers are tiled as seq_len // num_learnable_registers repeats of the register block to replace padding.

Source

Thrown at python/sglang/multimodal_gen/runtime/models/adapter/ltx_2_connector.py:452

            self.inner_dim, eps=eps, elementwise_affine=False
        )

        self.gradient_checkpointing = False

    def forward(
        self,
        hidden_states: torch.Tensor,
        attention_mask: Optional[torch.Tensor] = None,
        attn_mask_binarize_threshold: float = -9000.0,
    ) -> Tuple[torch.Tensor, torch.Tensor]:
        # hidden_states shape: [batch_size, seq_len, hidden_dim]
        # attention_mask shape: [batch_size, seq_len] or [batch_size, 1, 1, seq_len]
        batch_size, seq_len, _ = hidden_states.shape

        # 1. Replace padding with learned registers, if using
        if self.learnable_registers is not None:
            if seq_len % self.num_learnable_registers != 0:
                raise ValueError(
                    f"The `hidden_states` sequence length {hidden_states.shape[1]} should be divisible by the number"
                    f" of learnable registers {self.num_learnable_registers}"
                )

            num_register_repeats = seq_len // self.num_learnable_registers
            registers = torch.tile(
                self.learnable_registers, (num_register_repeats, 1)
            )  # [seq_len, inner_dim]

            binary_attn_mask = (attention_mask >= attn_mask_binarize_threshold).int()
            if binary_attn_mask.ndim == 4:
                binary_attn_mask = binary_attn_mask.squeeze(1).squeeze(
                    1
                )  # [B, 1, 1, L] --> [B, L]

            hidden_states_non_padded = [
                hidden_states[i, binary_attn_mask[i].bool(), :]
                for i in range(batch_size)

View on GitHub (pinned to 0132848349)

Solutions

  1. Pad hidden_states so seq_len is a multiple of num_learnable_registers (the module expects padding present by design)
  2. Set num_learnable_registers to a value that divides your token count (commonly 1 or a small divisor)
  3. Recompute expected seq_len from (frames/patches) and align it with the register config

Example fix

// before
out = connector(hidden_states)  # seq_len=100, num_learnable_registers=4
// after
pad = (-hidden_states.shape[1]) % connector.num_learnable_registers
hidden_states = torch.nn.functional.pad(hidden_states, (0,0,0,pad,0,0))
out = connector(hidden_states)
Defensive patterns

Strategy: validation

Validate before calling

n = connector.num_learnable_registers
if connector.learnable_registers is not None and hidden_states.shape[1] % n != 0:
    pad = (-hidden_states.shape[1]) % n
    hidden_states = torch.nn.functional.pad(hidden_states, (0,0,0,pad,0,0))

Prevention

When it happens

Trigger: Passing hidden_states whose sequence length (e.g. number of video tokens/patches) is not a multiple of num_learnable_registers while learnable_registers is not None.

Common situations: Custom resolutions or frame counts producing token counts not divisible by the register count; changing num_learnable_registers in config without adjusting patchified token counts; packing variable-length sequences.

Related errors


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