{"record":{"id":"a96c9ad522ea0b90","repo":"sgl-project/sglang","slug":"block-sparse-tensors-context-must-share-the-same","errorCode":null,"errorMessage":"Block sparse tensors{context} must share the same m-block dimension.","messagePattern":"Block sparse tensors(.+?) must share the same m-block dimension\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/attention/flash_attn/cute/block_sparsity.py","lineNumber":390,"sourceCode":"        )\n    if mask_block_cnt.ndim != 3 or mask_block_idx.ndim != 4:\n        raise ValueError(\n            f\"Block sparse tensors{context} must have shapes (B, H, M) and (B, H, M, N).\"\n        )\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        )","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/attention/flash_attn/cute/block_sparsity.py#L372-L408","documentation":"Raised when mask_block_cnt.shape[2] (m-block count) differs from mask_block_idx.shape[2]. The two tensors must enumerate the same set of query blocks so counts align with index rows.","triggerScenarios":"cnt built with M=32 m-blocks and idx with M=33 (e.g. different ceildiv rounding or inconsistent seqlen_q used to build each).","commonSituations":"Building cnt and idx in separate code paths that rounded seqlen_q/block_size differently, or editing one tensor during debugging.","solutions":["Rebuild both from the same num_m_blocks = ceildiv(seqlen_q, sparse_block_size_q)","Truncate/pad the inconsistent tensor so shape[2] matches"],"exampleFix":"// before\ncnt = torch.zeros((B,H,33), ...); idx = torch.zeros((B,H,32,N), ...)\n// after\nM = (seqlen_q + q_bs - 1) // q_bs\ncnt = torch.zeros((B,H,M), ...); idx = torch.zeros((B,H,M,N), ...)","handlingStrategy":"validation","validationCode":"assert mask_block_cnt.shape[2] == mask_block_idx.shape[2]","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compute M once and use it for both tensors","Derive both from the same seqlen_q and block size"],"tags":["block-sparse","shape-mismatch","consistency"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}