sgl-project/sglang · error · ValueError
img_position_ids must be [1, S, 3], got {list(img_position_i
Error message
img_position_ids must be [1, S, 3], got {list(img_position_ids.shape)} What it means
MiniMax H3's RoPE embedding module expects image position ids of exact shape [1, S, 3] (batch 1, sequence S, coords t/h/w). It validates dims and shape[0]==1 and raises otherwise, since downstream indexing img_position_ids[0] assumes that layout.
Source
Thrown at python/sglang/multimodal_gen/runtime/models/dits/minimax_h3.py:425
class MiniMaxH3Rope(nn.Module):
"""3D rope over (t, h, w); rotates 96 of 128 head dims (rotary_percent 0.75).
Frequency layout concatenates temporal, height, and width embeddings twice,
with 16 frequencies per axis (inv_freq = base^-(arange(0,32,2)/32)).
"""
def __init__(self, inv_freq_len: int) -> None:
super().__init__()
self.register_buffer(
"inv_freq",
torch.empty(inv_freq_len, dtype=_FP32_DTYPE),
persistent=True,
)
def forward(self, img_position_ids: torch.Tensor) -> torch.Tensor:
"""img_position_ids: [1, S, 3] (t, h, w) -> freqs [S, rot_dim=96]."""
if img_position_ids.dim() != 3 or img_position_ids.shape[0] != 1:
raise ValueError(
"img_position_ids must be [1, S, 3], got "
f"{list(img_position_ids.shape)}"
)
pos = img_position_ids[0].to(_FP32_DTYPE) # [S, 3]
per_axis = pos.unsqueeze(-1) * self.inv_freq.view(1, 1, -1) # [S, 3, 16]
t_f, h_f, w_f = per_axis.unbind(dim=1) # each [S, 16]
half = torch.cat((t_f, h_f, w_f), dim=-1) # [S, 48]
return torch.cat((half, half), dim=-1) # [S, 96]
def _rope_cos_sin_cache(freqs: torch.Tensor, *, dtype: torch.dtype) -> torch.Tensor:
"""Build the activation-dtype cos|sin cache for fused Q/K RoPE."""
half = freqs.shape[-1] // 2
return (
torch.cat(
(torch.cos(freqs[:, :half]), torch.sin(freqs[:, :half])),
dim=-1,
)View on GitHub (pinned to 0132848349)
Solutions
- Reshape to exactly [1, S, 3] before calling forward: ids.squeeze(0) if batched per-sample then process one at a time, or ids[0:1] to take batch dim of 1
- If truly batching, loop over the batch or ensure the module is called per sample since it only supports batch 1
- Fix the position-id generator to emit [1, S, 3] (t, h, w stacked on the last axis)
Example fix
# before freqs = rope(img_position_ids) # shape [B, S, 3] # after assert img_position_ids.shape[0] == 1 freqs = rope(img_position_ids) # pass ids[0:1] or per-sample slice
Defensive patterns
Strategy: type-guard
Validate before calling
assert img_position_ids.dim() == 3 and img_position_ids.shape[0] == 1 and img_position_ids.shape[-1] == 3, 'need [1, S, 3]'
Type guard
def is_valid_pos_ids(t: torch.Tensor) -> bool:
return t.dim() == 3 and t.shape[0] == 1 and t.shape[2] == 3 Prevention
- Standardize position-id builders to emit [1, S, 3]
- Process batched samples one at a time through RoPE modules that assume batch 1
When it happens
Trigger: Passing img_position_ids with batch > 1 (e.g. [B,S,3] from a batched pipeline), a squeezed [S,3] tensor, or a 4-D tensor; common when callers broadcast or stack per-sample position ids.
Common situations: Batched generation code producing [B,S,3] position ids; position-id builders from other models (LLM-style [1,S] or [B,S]) reused here; accidental unsqueeze/expand of the coords.
Related errors
- Qwen-VL position_ids do not match the attention input
- unsupported input for LTX2 QKNorm split-RoPE CUDA
- fl2va requires first_frame, last_frame, or both
- ref2va requires at least one of reference_image, reference_v
- t2va takes no conditioning inputs; pick another task
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/d72219a64fc871d3.
Report an issue: GitHub.