{"record":{"id":"e78a859c300e0c7a","repo":"sgl-project/sglang","slug":"flash-attn-varlen-func-op-is-out-only-op-return-s","errorCode":null,"errorMessage":"flash_attn_varlen_func_op is out-only op; return_softmax_lse must be False. Use flash_attn_varlen_func_op_lse for (out, lse).","messagePattern":"flash_attn_varlen_func_op is out-only op; return_softmax_lse must be False\\. Use flash_attn_varlen_func_op_lse for \\(out, lse\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/layers/attention/backends/flash_attn.py","lineNumber":197,"sourceCode":"    causal: bool = False,\n    qv: Optional[torch.Tensor] = None,\n    q_descale: Optional[torch.Tensor] = None,\n    k_descale: Optional[torch.Tensor] = None,\n    v_descale: Optional[torch.Tensor] = None,\n    window_size: Optional[List[int]] = None,\n    attention_chunk: int = 0,\n    softcap: float = 0.0,\n    num_splits: int = 1,\n    pack_gqa: Optional[bool] = None,\n    sm_margin: int = 0,\n    return_softmax_lse: bool = False,\n    sinks: Optional[torch.Tensor] = None,\n    ver: int = 4,\n) -> torch.Tensor:\n    if window_size is None:\n        window_size = [-1, -1]\n    if return_softmax_lse:\n        raise ValueError(\n            \"flash_attn_varlen_func_op is out-only op; return_softmax_lse must be False. \"\n            \"Use flash_attn_varlen_func_op_lse for (out, lse).\"\n        )\n    return flash_attn_varlen_func(\n        q,\n        k,\n        v,\n        cu_seqlens_q=cu_seqlens_q,\n        cu_seqlens_k=cu_seqlens_k,\n        max_seqlen_q=max_seqlen_q,\n        max_seqlen_k=max_seqlen_k,\n        seqused_q=seqused_q,\n        seqused_k=seqused_k,\n        page_table=page_table,\n        softmax_scale=softmax_scale,\n        causal=causal,\n        qv=qv,\n        q_descale=q_descale,","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/layers/attention/backends/flash_attn.py#L179-L215","documentation":"flash_attn_varlen_func_op is the out-only variant of the packed varlen flash-attention wrapper; passing return_softmax_lse=True is a misuse because the function cannot return the LSE. The wrapper rejects it to keep the return type honest.","triggerScenarios":"Calling flash_attn_varlen_func_op(..., return_softmax_lse=True); the check trips before any kernel dispatch.","commonSituations":"Code refactored from a single API that took a return_softmax_lse flag for both variants; adding LSE support (ring attention, logprob capture) by flipping the flag instead of switching functions.","solutions":["Switch the call to flash_attn_varlen_func_op_lse(...) and unpack (out, lse)","If only output is needed, pass return_softmax_lse=False (the default)"],"exampleFix":"# before\nout = flash_attn_varlen_func_op(q, k, v, cu_q, cu_k, mq, mk, return_softmax_lse=True)\n# after\nout, lse = flash_attn_varlen_func_op_lse(q, k, v, cu_q, cu_k, mq, mk, return_softmax_lse=True)","handlingStrategy":"validation","validationCode":"assert not return_softmax_lse, \"use flash_attn_varlen_func_op_lse for (out, lse)\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the _lse variant whenever you need the LSE","Never thread a shared return_softmax_lse flag into both variants"],"tags":["flash-attention","varlen","api-misuse","lse"],"backgroundTag":"wrong-api-variant-called","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}