sgl-project/sglang · error · ValueError

Block sparse tensors{context} m-block dimension {num_m_block

Error message

Block sparse tensors{context} m-block dimension {num_m_blocks} does not match sparse_block_size_q={sparse_block_size_q}. Set BlockSparseTensorsTorch.block_size to match the BlockMask BLOCK_SIZE.

What it means

Raised when the m-block dimension of the mask does not match the number of q blocks implied by sparse_block_size_q (expected_m_blocks = ceildiv(seqlen_q, sparse_block_size_q)). Usually means the BlockMask was built with a different q block size than recorded/requested.

Source

Thrown at python/sglang/kernels/ops/attention/flash_attn/cute/block_sparsity.py:400

            raise ValueError(
                f"Block sparse tensors{context} {dim_name} dim must be {tgt} or 1."
            )
    for dim_name, cur, tgt in (
        ("batch", mask_block_idx.shape[0], expected_index_shape[0]),
        ("head", mask_block_idx.shape[1], expected_index_shape[1]),
    ):
        if cur != tgt and cur != 1:
            raise ValueError(
                f"Block sparse tensors{context} {dim_name} dim must be {tgt} or 1."
            )
    if mask_block_cnt.shape[2] != mask_block_idx.shape[2]:
        raise ValueError(
            f"Block sparse tensors{context} must share the same m-block dimension."
        )
    # [Note] Allow Compact block sparse indices: FA4 only accesses indices 0..cnt-1
    # per query tile, so idx.shape[3] can be <= expected_n_blocks.
    if mask_block_idx.shape[3] > expected_n_blocks:
        raise ValueError(
            f"Block sparse tensors{context} n-block dimension must be <= {expected_n_blocks}."
        )
    if expected_m_blocks != num_m_blocks:
        raise ValueError(
            f"Block sparse tensors{context} m-block dimension {num_m_blocks} does not match "
            f"sparse_block_size_q={sparse_block_size_q}. "
            f"Set BlockSparseTensorsTorch.block_size to match the BlockMask BLOCK_SIZE."
        )
    return expected_count_shape, expected_index_shape, q_subtile_factor


def get_block_sparse_expected_shapes_bwd(
    batch_size: int,
    num_head: int,
    seqlen_q: int,
    seqlen_k: int,
    m_block_size: int,
    n_block_size: int,

View on GitHub (pinned to 0132848349)

Solutions

  1. Set BlockSparseTensorsTorch.block_size to the BlockMask's BLOCK_SIZE so sparse_block_size_q matches the mask layout
  2. Rebuild the mask with q block size consistent with the current seqlen_q
  3. Recheck that seqlen_q (e.g. including spec-decode extra tokens) matches mask construction

Example fix

// before
tensors = BlockSparseTensorsTorch(cnt, idx)  # block_size unset
// after
tensors = BlockSparseTensorsTorch(cnt, idx, block_size=(128, 128))  # match BlockMask
Defensive patterns

Strategy: validation

Validate before calling

expected_m = (seqlen_q + sparse_block_size_q - 1) // sparse_block_size_q
assert mask_block_idx.shape[2] == expected_m

Prevention

When it happens

Trigger: num_m_blocks=64 from the mask but ceildiv(seqlen_q, sparse_block_size_q)=32, during normalize_block_sparse_config.

Common situations: BlockSparseTensorsTorch.block_size not set (or stale) after converting a BlockMask, so sparse_block_size_q defaults incorrectly; or seqlen_q changed between mask build and call.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/963781c441169027. Report an issue: GitHub.