{"record":{"id":"9ea187f6c7833aeb","repo":"sgl-project/sglang","slug":"expected-x-shape-1-to-be-even-for-split-rotary-9ea187","errorCode":null,"errorMessage":"Expected x.shape[-1] to be even for split rotary, got {last}.","messagePattern":"Expected x\\.shape\\[-1\\] to be even for split rotary, got (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/models/dits/ltx_2.py","lineNumber":347,"sourceCode":"        and x.is_contiguous()\n        and cos.is_cuda\n        and sin.is_cuda\n    ):\n        from sglang.kernels.ops.diffusion import apply_ltx2_split_rotary_emb\n\n        return apply_ltx2_split_rotary_emb(x, cos, sin)\n\n    x_dtype = x.dtype\n    needs_reshape = False\n    if x.ndim != 4 and cos.ndim == 4:\n        b = x.shape[0]\n        _, h, t, _ = cos.shape\n        x = x.reshape(b, t, h, -1).swapaxes(1, 2)\n        needs_reshape = True\n\n    last = x.shape[-1]\n    if last % 2 != 0:\n        raise ValueError(\n            f\"Expected x.shape[-1] to be even for split rotary, got {last}.\"\n        )\n    r = last // 2\n\n    split_x = x.reshape(*x.shape[:-1], 2, r)\n    first_x = split_x[..., :1, :]\n    second_x = split_x[..., 1:, :]\n\n    cos_u = cos.unsqueeze(-2)\n    sin_u = sin.unsqueeze(-2)\n\n    out = split_x * cos_u\n    first_out = out[..., :1, :]\n    second_out = out[..., 1:, :]\n    first_out.addcmul_(-sin_u, second_x)\n    second_out.addcmul_(sin_u, first_x)\n\n    out = out.reshape(*out.shape[:-2], last)","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/models/dits/ltx_2.py#L329-L365","documentation":"LTX-2's split rotary embedding halves the feature dimension (rotate_half style), so the last axis must be even. apply_split_rotary_emb checks x.shape[-1] % 2 before reshaping to (..., 2, r) and errors on odd sizes.","triggerScenarios":"Calling apply_split_rotary_emb with a tensor whose last dim is odd, e.g. head_dim of 67, or a partially sliced/projected q/k tensor with an off-by-one cut.","commonSituations":"Custom head dims in config; slicing q/k after projection with wrong end index; feeding interleaved-layout tensors into the split-rotary path.","solutions":["Use an even head_dim / last-dim size in the model config","Fix upstream slicing so the tensor reaching this function keeps its full even width","Route tensors with odd dims (if intentional) through a padding step or the interleaved rope path"],"exampleFix":"# before\nq = q[..., :67]               # odd trailing dim\nq = apply_split_rotary_emb(q, cos, sin)\n\n# after\nq = q[..., :68]               # even head_dim\nq = apply_split_rotary_emb(q, cos, sin)","handlingStrategy":"validation","validationCode":"assert x.shape[-1] % 2 == 0, f'split rotary needs even last dim, got {x.shape[-1]}'","typeGuard":"def has_even_last_dim(t: torch.Tensor) -> bool:\\n    return t.shape[-1] % 2 == 0","tryCatchPattern":null,"preventionTips":["Use standard even head_dims (64/128)","Avoid slicing q/k after projection","Test rotary helpers with odd-shaped dummy tensors"],"tags":["rope","shape-validation","ltx2","even-dimension"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}