{"record":{"id":"3828571dc62a890d","repo":"sgl-project/sglang","slug":"b-must-have-shape-b-hv-with-hv-hv-got-b-sh-382857","errorCode":null,"errorMessage":"`b` must have shape [B, HV] with HV={HV} (got b.shape={tuple(b.shape)}).","messagePattern":"`b` must have shape \\[B, HV\\] with HV=(.+?) \\(got b\\.shape=(.+?)\\)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/attention/helion/kda_decode.py","lineNumber":298,"sourceCode":"    if initial_state.ndim != 4:\n        raise ValueError(\n            f\"`initial_state` must be a 4D tensor (got ndim={initial_state.ndim}).\"\n        )\n    if initial_state.stride(-1) != 1:\n        raise ValueError(\"`initial_state` must be contiguous in the last dim.\")\n    HV, V, K = initial_state.shape[-3:]\n    if not _is_power_of_two(K) or not _is_power_of_two(V):\n        raise ValueError(\n            \"Helion KDA decode requires power-of-two key and value head \"\n            f\"dimensions (got K={K}, V={V}).\"\n        )\n    if a.shape[1] != HV * K:\n        raise ValueError(\n            f\"`a` must have shape [B, HV*K] with HV={HV}, K={K} \"\n            f\"(got a.shape={tuple(a.shape)}).\"\n        )\n    if b.shape[1] != HV:\n        raise ValueError(\n            f\"`b` must have shape [B, HV] with HV={HV} (got b.shape={tuple(b.shape)}).\"\n        )\n    if A_log.numel() != HV:\n        raise ValueError(f\"`A_log` must have {HV} elements (got {A_log.numel()}).\")\n    if dt_bias.numel() != HV * K:\n        raise ValueError(\n            f\"`dt_bias` must have {HV * K} elements (got {dt_bias.numel()}).\"\n        )\n    if out.shape != (B, 1, HV, V):\n        raise ValueError(\n            f\"`out` must have shape {(B, 1, HV, V)} (got out.shape={tuple(out.shape)}).\"\n        )\n\n    qkv_dim = mixed_qkv.shape[1]\n    qk_dim = qkv_dim - HV * V\n    if qk_dim <= 0 or qk_dim % 2 != 0:\n        raise ValueError(\n            f\"Invalid packed `mixed_qkv` last dim={qkv_dim} for HV={HV}, V={V}.\"","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/attention/helion/kda_decode.py#L280-L316","documentation":"The KDA gate/input tensor `b` must be packed as [B, HV]: one scalar gate per value head per batch row. validate_packed_decode_inputs checks b.shape[1] == HV (HV inferred from initial_state) and raises when b carries per-key or per-token values instead.","triggerScenarios":"Passing `b` with shape [B, HV*K] (per-key gates), [B, 1], or [B, H] where H is the query-head count rather than the value-head count.","commonSituations":"Reusing the packing used for `a` for `b` as well; confusing num_k_heads with num_v_heads in GQA-style KDA models (H != HV); slicing a projection output with the wrong width.","solutions":["Reshape b to [B, HV]: b = b_proj_out.reshape(B, -1) and confirm the projection width equals num_v_heads","Double-check that HV comes from initial_state.shape[-3] and matches the model's num_v_heads, not num_q_heads","Write a shape check in the model forward: assert b.shape == (B, num_v_heads)"],"exampleFix":"// before\nb = gates  # [B, HV*K] accidentally\n// after\nb = gates.reshape(B, -1)\nassert b.shape[1] == initial_state.shape[-3]","handlingStrategy":"validation","validationCode":"HV = initial_state.shape[-3]\nb = b.reshape(b.size(0), -1)\nassert b.shape[1] == HV, (b.shape, HV)","typeGuard":"def valid_packed_b(b: torch.Tensor, hv: int) -> bool:\n    return b.ndim == 2 and b.shape[1] == hv","tryCatchPattern":null,"preventionTips":["Never reuse the `a` packing width for `b`","Log num_v_heads once at startup and use it for all gate widths"],"tags":["kda","helion","shape-validation","packed-layout"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}