{"record":{"id":"d7d025016b173fc0","repo":"sgl-project/sglang","slug":"a-and-b-must-be-2d-tensors-got-a-ndim-a-ndim-d7d025","errorCode":null,"errorMessage":"`a` and `b` must be 2D tensors (got a.ndim={a.ndim}, b.ndim={b.ndim}).","messagePattern":"`a` and `b` must be 2D tensors \\(got a\\.ndim=(.+?), b\\.ndim=(.+?)\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/attention/helion/kda_decode.py","lineNumber":235,"sourceCode":"def validate_packed_decode_inputs(\n    mixed_qkv: torch.Tensor,\n    a: torch.Tensor,\n    b: torch.Tensor,\n    A_log: torch.Tensor,\n    dt_bias: torch.Tensor,\n    initial_state: torch.Tensor,\n    out: torch.Tensor,\n    ssm_state_indices: torch.Tensor,\n) -> tuple[int, int, int, int, int]:\n    \"\"\"Apply the shape and layout checks from SGLang's packed wrapper.\"\"\"\n    if mixed_qkv.ndim != 2:\n        raise ValueError(\n            f\"`mixed_qkv` must be a 2D tensor (got ndim={mixed_qkv.ndim}).\"\n        )\n    if mixed_qkv.stride(-1) != 1:\n        raise ValueError(\"`mixed_qkv` must be contiguous in the last dim.\")\n    if a.ndim != 2 or b.ndim != 2:\n        raise ValueError(\n            f\"`a` and `b` must be 2D tensors (got a.ndim={a.ndim}, b.ndim={b.ndim}).\"\n        )\n    if a.stride(-1) != 1 or b.stride(-1) != 1:\n        raise ValueError(\"`a`/`b` must be contiguous in the last dim.\")\n    if A_log.ndim != 1 or dt_bias.ndim != 1:\n        raise ValueError(\"`A_log`/`dt_bias` must be 1D tensors.\")\n    if A_log.stride(0) != 1 or dt_bias.stride(0) != 1:\n        raise ValueError(\"`A_log`/`dt_bias` must be contiguous.\")\n    if ssm_state_indices.ndim != 1:\n        raise ValueError(\n            \"`ssm_state_indices` must be 1D for packed decode \"\n            f\"(got ndim={ssm_state_indices.ndim}).\"\n        )\n    if not out.is_contiguous():\n        raise ValueError(\"`out` must be contiguous.\")\n\n    device = mixed_qkv.device\n    if any(","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/attention/helion/kda_decode.py#L217-L253","documentation":"The KDA packed decode kernel requires the gated delta-rule a and b tensors as 2D [B, dim] tensors. Passing tensors with any other rank fails validation before kernel launch.","triggerScenarios":"Calling packed decode with a/b of ndim != 2, e.g. [B, seq, d] or [B, n_groups, d].","commonSituations":"Using prefill-shaped a/b tensors during decode; forgetting to squeeze a seq or head dim after scheduling.","solutions":["Reshape a and b to 2D matching mixed_qkv's batch size","Verify the host wrapper producing a/b emits [B, D]"],"exampleFix":"# before\nout = decode(qkv, a_3d, b_3d, ...)\n# after\nout = decode(qkv, a_3d.reshape(a_3d.shape[0], -1), b_3d.reshape(b_3d.shape[0], -1), ...)","handlingStrategy":"validation","validationCode":"assert a.ndim == 2 and b.ndim == 2, f'a/b must be 2D, got {a.ndim}, {b.ndim}'","typeGuard":"def are_2d(*ts: torch.Tensor) -> bool:\n    return all(t.ndim == 2 for t in ts)","tryCatchPattern":null,"preventionTips":["Squeeze seq dims after scheduling decode batches","Shape-assert in the wrapper before kernel launch"],"tags":["kda","mamba","tensor-shape","helion"],"backgroundTag":"invalid-tensor-shape","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}