{"record":{"id":"3cf14dfa56ba84a4","repo":"sgl-project/sglang","slug":"mask-block-cnt-and-mask-block-idx-must-be-provided","errorCode":null,"errorMessage":"mask_block_cnt and mask_block_idx must be provided for block sparsity.","messagePattern":"mask_block_cnt and mask_block_idx must be provided for block sparsity\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/attention/flash_attn/cute/block_sparsity.py","lineNumber":340,"sourceCode":"\n    Expectations:\n    - mask_block_cnt is (B, H, M) and mask_block_idx is (B, H, M, N).\n    - Batch/head dims may be 1 for broadcast, or match the requested sizes.\n    - sparse_block_size_kv must match tile_n.\n    - sparse_block_size_q must be a multiple of q_stage * tile_m.\n    - If sparse_block_size_q is omitted and seqlen_q/num_m_blocks is ambiguous,\n      the caller must provide block_size to disambiguate. TODO will make this required in a future PR.\n    \"\"\"\n    base_m_block = q_stage * m_block_size\n    base_n_block = n_block_size\n    if sparse_block_size_kv is None:\n        sparse_block_size_kv = base_n_block\n    if sparse_block_size_kv != base_n_block:\n        raise ValueError(\n            f\"Block sparse tensors{context} require BLOCK_SIZE_KV={base_n_block}.\"\n        )\n    if tensors.mask_block_idx is None:\n        raise ValueError(\n            \"mask_block_cnt and mask_block_idx must be provided for block sparsity.\"\n        )\n    num_m_blocks = tensors.mask_block_idx.shape[2]\n\n    if sparse_block_size_q is None:\n        sparse_block_size_q = get_sparse_q_block_size(tensors, seqlen_q)\n        if sparse_block_size_q is None and base_m_block != 1:\n            raise ValueError(\n                f\"Block sparse tensors{context} require explicit sparse_block_size[0] \"\n                f\"to disambiguate block size for seqlen_q={seqlen_q} and num_m_blocks={num_m_blocks}.\"\n            )\n        if sparse_block_size_q is None:\n            sparse_block_size_q = ceildiv(seqlen_q, num_m_blocks)\n\n    if sparse_block_size_q % base_m_block != 0:\n        raise ValueError(\n            f\"Block sparse tensors{context} have block size {sparse_block_size_q}, \"\n            f\"which must be a multiple of {base_m_block}.\"","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/attention/flash_attn/cute/block_sparsity.py#L322-L358","documentation":"Raised during shape inference when mask_block_idx (and cnt) is missing from the block-sparse tensor bundle. Block sparsity cannot operate without at least the mask indices/counts.","triggerScenarios":"Constructing BlockSparseTensorsTorch with only full_block_cnt/full_block_idx (or empty) and calling normalize_block_sparse_config.","commonSituations":"Converting a BlockMask that only carries 'full' blocks, or a partial conversion utility that dropped the mask fields.","solutions":["Provide mask_block_cnt and mask_block_idx (shapes (B,H,M) and (B,H,M,N))","If the mask genuinely has no sparse blocks, pass all-zero/int32-empty mask tensors rather than None"],"exampleFix":"// before\ntensors = BlockSparseTensorsTorch(mask_block_cnt=None, mask_block_idx=None, ...)\n// after\ntensors = BlockSparseTensorsTorch(mask_block_cnt=cnt, mask_block_idx=idx, ...)","handlingStrategy":"type-guard","validationCode":"assert tensors.mask_block_cnt is not None and tensors.mask_block_idx is not None","typeGuard":"def has_mask(t): return t.mask_block_cnt is not None and t.mask_block_idx is not None","tryCatchPattern":null,"preventionTips":["Validate the bundle right after construction","Check BlockMask conversion preserves mask fields"],"tags":["block-sparse","missing-argument","validation"],"backgroundTag":"missing-required-parameter","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}