{"record":{"id":"1ee4b710787cf4e3","repo":"sgl-project/sglang","slug":"block-sparse-tensors-context-n-block-dimension-mu","errorCode":null,"errorMessage":"Block sparse tensors{context} n-block dimension must be <= {expected_n_blocks}.","messagePattern":"Block sparse tensors(.+?) n-block dimension must be <= (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/attention/flash_attn/cute/block_sparsity.py","lineNumber":394,"sourceCode":"        )\n    for dim_name, cur, tgt in (\n        (\"batch\", mask_block_cnt.shape[0], expected_count_shape[0]),\n        (\"head\", mask_block_cnt.shape[1], expected_count_shape[1]),\n    ):\n        if cur != tgt and cur != 1:\n            raise ValueError(\n                f\"Block sparse tensors{context} {dim_name} dim must be {tgt} or 1.\"\n            )\n    for dim_name, cur, tgt in (\n        (\"batch\", mask_block_idx.shape[0], expected_index_shape[0]),\n        (\"head\", mask_block_idx.shape[1], expected_index_shape[1]),\n    ):\n        if cur != tgt and cur != 1:\n            raise ValueError(\n                f\"Block sparse tensors{context} {dim_name} dim must be {tgt} or 1.\"\n            )\n    if mask_block_cnt.shape[2] != mask_block_idx.shape[2]:\n        raise ValueError(\n            f\"Block sparse tensors{context} must share the same m-block dimension.\"\n        )\n    # [Note] Allow Compact block sparse indices: FA4 only accesses indices 0..cnt-1\n    # per query tile, so idx.shape[3] can be <= expected_n_blocks.\n    if mask_block_idx.shape[3] > expected_n_blocks:\n        raise ValueError(\n            f\"Block sparse tensors{context} n-block dimension must be <= {expected_n_blocks}.\"\n        )\n    if expected_m_blocks != num_m_blocks:\n        raise ValueError(\n            f\"Block sparse tensors{context} m-block dimension {num_m_blocks} does not match \"\n            f\"sparse_block_size_q={sparse_block_size_q}. \"\n            f\"Set BlockSparseTensorsTorch.block_size to match the BlockMask BLOCK_SIZE.\"\n        )\n    return expected_count_shape, expected_index_shape, q_subtile_factor\n\n\ndef get_block_sparse_expected_shapes_bwd(","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/attention/flash_attn/cute/block_sparsity.py#L376-L412","documentation":"Raised when mask_block_idx's n-block dimension exceeds expected_n_blocks = ceildiv(seqlen_k, sparse_block_size_kv). Larger is invalid; smaller is intentionally allowed (compact indices, since FA4 only reads 0..cnt-1 per tile).","triggerScenarios":"idx.shape[3]=128 when seqlen_k/block_size gives only 64 KV blocks — indices could point past the KV sequence.","commonSituations":"Mask generated for a longer KV length than the current call's k/v tensors (e.g. cached mask with larger max_seqlen), or wrong seqlen_k passed to the shape inference.","solutions":["Regenerate the mask for the current seqlen_k / KV cache length","Trim idx.shape[3] to expected_n_blocks (safe since only 0..cnt-1 are read): idx = idx[..., :expected_n_blocks]","Verify seqlen_k passed matches the actual k tensor length"],"exampleFix":"// before\nidx = cached_idx  # (B,H,M,128) but only 64 kv blocks\n// after\nidx = cached_idx[..., :64]","handlingStrategy":"validation","validationCode":"expected_n = (seqlen_k + sparse_block_size_kv - 1) // sparse_block_size_kv\nassert mask_block_idx.shape[3] <= expected_n","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Regenerate cached masks when seqlen_k shrinks","Trimming idx[..., :expected_n] is safe (only 0..cnt-1 read)"],"tags":["block-sparse","shape-mismatch","kv-length"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}