{"record":{"id":"651b19dc0801f380","repo":"sgl-project/sglang","slug":"lora-batch-info-must-provide-max-len-or-seg-lens","errorCode":null,"errorMessage":"LoRA batch_info must provide max_len or seg_lens.","messagePattern":"LoRA batch_info must provide max_len or seg_lens\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/gemm/kv_b_lora_absorbed.py","lineNumber":89,"sourceCode":"# ---------------------------------------------------------------------------\n\n_BLOCK_S = 16\n_STEP_A_BLOCK_K = 64  # contraction over qk_nope (~128) or kv_lora_rank (~512)\n_STEP_A_BLOCK_N = 16  # output is rank\n_STEP_B_BLOCK_K = 16  # contraction is rank\n_STEP_B_BLOCK_N = 64  # output is kv_lora_rank (~512) or v_head_dim (~128)\n\n\ndef _num_segments(batch_info: LoRABatchInfo) -> int:\n    return batch_info.num_segments or batch_info.bs\n\n\ndef _max_segment_len(batch_info: LoRABatchInfo) -> int:\n    if batch_info.max_len is not None:\n        return batch_info.max_len\n    if batch_info.seg_lens is not None:\n        return int(batch_info.seg_lens.max().item())\n    raise ValueError(\"LoRA batch_info must provide max_len or seg_lens.\")\n\n\ndef _segment_grid_size(batch_info: LoRABatchInfo, num_segments: int) -> int:\n    return (\n        batch_info.weight_indices.shape[0]\n        if batch_info.use_cuda_graph\n        else num_segments\n    )\n\n\n# ---------------------------------------------------------------------------\n# Kernel 1 -- Step A_q: per-head per-slot SGMM, reads K-half of B\n#\n#     q_lora_a[t, h, r] = sum_{i<qk_nope} q_nope[t, h, i] * B[slot, h*FULL_K + i, r]\n#\n# x      : (S, H, qk_nope)\n# w (B)  : (num_lora, H*FULL_K, rank)   -- FULL_K = qk_nope + v_head_dim\n# out    : (S, H, rank)                 -- fresh allocation, no accumulate","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/gemm/kv_b_lora_absorbed.py#L71-L107","documentation":"The KV-B absorbed LoRA GEMM steps need the maximum segment length to size Triton grids; LoRABatchInfo must carry either max_len or seg_lens. If both are None, _max_segment_len cannot derive it and raises.","triggerScenarios":"Constructing LoRABatchInfo with max_len=None and seg_lens=None, then calling step_a_q_fwd / step_b_q_fwd / step_a_v_fwd / step_b_v_fwd.","commonSituations":"Building batch info incrementally and forgetting to set max_len, or code paths that skip seg_lens computation for single-request batches.","solutions":["Set batch_info.max_len to an upper bound on segment length (e.g. precomputed max sequence length) before the call.","Or populate batch_info.seg_lens (a tensor of per-segment lengths) so max can be derived.","Compute max_len once at batch preparation and pass it through."],"exampleFix":"// before\ninfo = LoRABatchInfo(..., max_len=None, seg_lens=None)\n// after\ninfo = LoRABatchInfo(..., max_len=int(seg_lens.max().item()), seg_lens=seg_lens)","handlingStrategy":"validation","validationCode":"if info.max_len is None:\n    info.max_len = (int(info.seg_lens.max().item())\n                    if info.seg_lens is not None else default_max_len)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always populate max_len when building LoRABatchInfo.","Validate batch info in a helper before LoRA steps."],"tags":["lora","batch-info","missing-config"],"backgroundTag":"missing-required-config-field","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}