{"record":{"id":"e013e17448830ff5","repo":"sgl-project/sglang","slug":"time-must-have-shape-batch","errorCode":null,"errorMessage":"time must have shape [batch]","messagePattern":"time must have shape \\[batch\\]","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/models/vlas/pi05_core.py","lineNumber":835,"sourceCode":"            depth=18,\n            mlp_dim=16_384,\n            num_heads=8,\n            num_kv_heads=1,\n            head_dim=256,\n        )\n    raise ValueError(f\"Unknown Pi05 Gemma variant: {variant}\")\n\n\ndef create_sinusoidal_pos_embedding(\n    time: torch.Tensor,\n    dimension: int,\n    min_period: float,\n    max_period: float,\n) -> Tensor:\n    if dimension % 2 != 0:\n        raise ValueError(f\"dimension ({dimension}) must be divisible by 2\")\n    if time.ndim != 1:\n        raise ValueError(\"time must have shape [batch]\")\n    fraction = torch.linspace(\n        0.0,\n        1.0,\n        dimension // 2,\n        dtype=torch.float64,\n        device=time.device,\n    )\n    period = min_period * (max_period / min_period) ** fraction\n    scaling = 1.0 / period * 2 * math.pi\n    sin_input = scaling[None, :] * time[:, None].to(torch.float64)\n    return torch.cat([torch.sin(sin_input), torch.cos(sin_input)], dim=1)\n\n\ndef make_att_2d_masks(\n    pad_masks: torch.Tensor,\n    att_masks: torch.Tensor,\n) -> torch.Tensor:\n    if att_masks.ndim != 2 or pad_masks.ndim != 2:","sourceCodeStart":817,"sourceCodeEnd":853,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/models/vlas/pi05_core.py#L817-L853","documentation":"create_sinusoidal_pos_embedding expects the time input to be a 1-D tensor with shape [batch], one timestamp per sequence element. If time has more axes (e.g. [batch, seq] or a scalar 0-d tensor), the broadcasting logic downstream would silently produce wrong shapes, so the function guards ndim == 1 and raises. Called from embed_suffix.","triggerScenarios":"Passing time with shape [batch, 1], [batch, seq], or a 0-d scalar tensor; commonly from squeezing/unsqueezing mistakes or from feeding per-timestep tensors from the denoising loop without flattening.","commonSituations":"Adapting a diffusion timestep loop that yields [B,1] tensors; passing time = t.unsqueeze(0) by mistake; refactors that changed tensor rank.","solutions":["Flatten the time tensor before calling: time = time.reshape(-1) or time.squeeze()","If time is a scalar, materialize a 1-D tensor: time = torch.full((batch_size,), t, device=...)","Add an assert time.ndim == 1 upstream in your pipeline to catch rank drift early"],"exampleFix":"# before\ntime = torch.full((batch, 1), t, device=dev)  # shape [B, 1]\nemb = create_sinusoidal_pos_embedding(time, dim, pmin, pmax)\n\n# after\ntime = torch.full((batch,), t, device=dev)  # shape [B]\nemb = create_sinusoidal_pos_embedding(time, dim, pmin, pmax)","handlingStrategy":"validation","validationCode":"assert isinstance(time, torch.Tensor) and time.ndim == 1, (\n    f\"time must be [batch], got shape {tuple(time.shape)}\"\n)","typeGuard":"def is_batched_time(time: torch.Tensor) -> bool:\n    return isinstance(time, torch.Tensor) and time.ndim == 1","tryCatchPattern":"try:\n    emb = create_sinusoidal_pos_embedding(time, dim, pmin, pmax)\nexcept ValueError:\n    time = time.reshape(-1) if isinstance(time, torch.Tensor) else torch.as_tensor([time])\n    emb = create_sinusoidal_pos_embedding(time, dim, pmin, pmax)","preventionTips":["Standardize on [batch]-shaped timestep tensors throughout your diffusion loop","After any squeeze/unsqueeze refactor, run a smoke forward with tiny batch to catch rank drift"],"tags":["pi05","tensor-rank","input-validation"],"backgroundTag":"shape-validation-failed","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}