{"record":{"id":"9491e58ae1d432e3","repo":"sgl-project/sglang","slug":"invalid-packed-q-size-q-dim-must-be-divisible-b-9491e5","errorCode":null,"errorMessage":"Invalid packed Q size {q_dim}: must be divisible by K={K}. KDA packed decode requires num_q_heads == num_k_heads and head_q_dim == head_k_dim.","messagePattern":"Invalid packed Q size (.+?): must be divisible by K=(.+?)\\. KDA packed decode requires num_q_heads == num_k_heads and head_q_dim == head_k_dim\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/attention/helion/kda_decode.py","lineNumber":320,"sourceCode":"        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}.\"\n        )\n    q_dim = qk_dim // 2\n    if q_dim % K != 0:\n        raise ValueError(\n            f\"Invalid packed Q size {q_dim}: must be divisible by K={K}. \"\n            \"KDA packed decode requires num_q_heads == num_k_heads and \"\n            \"head_q_dim == head_k_dim.\"\n        )\n    H = q_dim // K\n    if H <= 0 or HV % H != 0:\n        raise ValueError(\n            f\"Invalid head config inferred from mixed_qkv: H={H}, HV={HV}.\"\n        )\n    return B, H, HV, K, V\n\n\ndef helion_fused_recurrent_kda_packed_decode(\n    mixed_qkv: torch.Tensor,\n    a: torch.Tensor,\n    b: torch.Tensor,\n    A_log: torch.Tensor,\n    dt_bias: torch.Tensor,","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/attention/helion/kda_decode.py#L302-L338","documentation":"After validating the even qk width, validate_packed_decode_inputs splits it in half to get the packed Q size and requires it to be a multiple of K (head_k_dim). This enforces the packed-decode constraint num_q_heads == num_k_heads and head_q_dim == head_k_dim, since the kernel indexes q as [H, K].","triggerScenarios":"A GQA layout where num_q_heads > num_k_heads is packed into mixed_qkv and passed to helion_fused_recurrent_kda_packed_decode; head_q_dim set differently from head_k_dim in the model config.","commonSituations":"Reusing a GQA attention config with the KDA packed decode kernel; migrating a model whose q heads were duplicated (MQA-style) without repacking; test tensors built with q width not a multiple of K.","solutions":["Fall back to a decode path that supports GQA, or repack q so num_q_heads == num_k_heads with head_q_dim == head_k_dim","Fix the model config: head_q_dim = head_k_dim and num_q_heads = num_k_heads","Assert (qkv.shape[1] - HV*V) % (2*K) == 0 before the call"],"exampleFix":"// before\n# config: num_q_heads=32, num_k_heads=8 (GQA)\nuse_packed_helion = True\n// after\nuse_packed_helion = (cfg.num_q_heads == cfg.num_k_heads and cfg.head_q_dim == cfg.head_k_dim)","handlingStrategy":"fallback","validationCode":"HV, V, K = initial_state.shape[-3:]\nq_dim = (mixed_qkv.shape[1] - HV * V) // 2\npacked_ok = q_dim % K == 0 and HV % (q_dim // K) == 0\nbackend = \"helion_packed\" if packed_ok else \"triton\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat num_q_heads == num_k_heads as a hard requirement for this kernel","Gate backend selection on inferred head layout at startup"],"tags":["kda","helion","gqa","head-config"],"backgroundTag":"unsupported-head-dimension","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}