sgl-project/sglang · error · ValueError
head_dim must be a multiple of 8, got {head_dim}.
Error message
head_dim must be a multiple of 8, got {head_dim}. What it means
The 3D RoPE embeddings in the LTX-2.5 diffusion decoder split head_dim into temporal and spatial rotation pairs; a head_dim not divisible by 8 cannot be split into whole even-sized halves, so init fails fast with this check.
Source
Thrown at python/sglang/multimodal_gen/runtime/models/decoders/ltx_2_5_diffusion_decoder.py:236
_compile=True,
)
if len(_BLOCK_MASK_CACHE) >= _BLOCK_MASK_CACHE_MAX:
_BLOCK_MASK_CACHE.pop(next(iter(_BLOCK_MASK_CACHE)))
_BLOCK_MASK_CACHE[cache_key] = block_mask
return block_mask
class LTX2VideoVaeRotaryPosEmbed3D(nn.Module):
"""Absolute 3D rotary embedding over the (T, H, W) grid.
`head_dim` splits into (T, H, W) chunks, each rotated by its own axis
position.
"""
def __init__(self, head_dim: int, base: float = 10000.0) -> None:
super().__init__()
if head_dim % 8 != 0:
raise ValueError(f"head_dim must be a multiple of 8, got {head_dim}.")
# A quarter to T, the rest split H/W, both kept even for whole
# rotation pairs.
dim_t = (head_dim // 4) // 2 * 2
dim_hw = (head_dim - dim_t) // 2
if dim_hw % 2 != 0:
dim_t -= 2
dim_hw = (head_dim - dim_t) // 2
self.rope_dim_split = (dim_t, dim_hw, dim_hw)
self.base = base
def _axis_tables(
self, length: int, dim: int, device: torch.device
) -> tuple[torch.Tensor, torch.Tensor]:
exponents = torch.arange(0, dim, 2, dtype=torch.float64, device=device) / dim
inv_freqs = (1.0 / self.base**exponents).to(torch.float32)
positions = torch.arange(length, dtype=torch.float32, device=device)
angles = positions[:, None] * inv_freqs[None, :]
return angles.cos(), angles.sin()View on GitHub (pinned to 0132848349)
Solutions
- Use a head_dim that is a multiple of 8 (64, 128, 32, ...)
- Keep the model's shipped default head_dim (usually 64) unless you have re-derived compatible dims
- Validate arch head_dim at config-load time before constructing the decoder
Example fix
# before rope = LtxRotaryEmbedding3D(head_dim=50) # after rope = LtxRotaryEmbedding3D(head_dim=48) # or 64
Defensive patterns
Strategy: validation
Validate before calling
if head_dim % 8 != 0:
raise ValueError(f"head_dim {head_dim} must be a multiple of 8") Type guard
def valid_head_dim(head_dim: int) -> bool:
return head_dim > 0 and head_dim % 8 == 0 Try / catch
try:
rope = LtxRotaryEmbedding3D(head_dim=head_dim)
except ValueError:
head_dim = (head_dim // 8) * 8 or 8
rope = LtxRotaryEmbedding3D(head_dim=head_dim) Prevention
- Keep head_dim in {8, 16, 32, 64, 128}
- Validate arch overrides in one place before constructing decoder modules
When it happens
Trigger: Constructing the RoPE module with head_dim values like 12, 20, 48+4, or any non-multiple of 8 (e.g. head_dim=50), typically via a custom arch config overriding decoder head_dim.
Common situations: Porting a model whose attention head_dim is unusual; hand-editing architecture hyperparameters; experimenting with smaller head dims to shrink parameters.
Related errors
- Expected x.shape[-1] to be even for split rotary, got {last}
- rope_pool_fused expects q/k/v to be 3-D
- rope_pool_fused expects positions/slots to be 1-D
- rope_pool_fused expects pool tensors to be 3-D
- q shape must be [num_tokens, num_qo_heads, head_dim], got {q
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/37ea5983351c3f08.
Report an issue: GitHub.