sgl-project/sglang · error · ValueError

Block sparse tensors{context} must share the same m-block di

Error message

Block sparse tensors{context} must share the same m-block dimension.

What it means

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.

Source

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

        )
    if mask_block_cnt.ndim != 3 or mask_block_idx.ndim != 4:
        raise ValueError(
            f"Block sparse tensors{context} must have shapes (B, H, M) and (B, H, M, N)."
        )
    for dim_name, cur, tgt in (
        ("batch", mask_block_cnt.shape[0], expected_count_shape[0]),
        ("head", mask_block_cnt.shape[1], expected_count_shape[1]),
    ):
        if cur != tgt and cur != 1:
            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."
        )

View on GitHub (pinned to 0132848349)

Solutions

  1. Rebuild both from the same num_m_blocks = ceildiv(seqlen_q, sparse_block_size_q)
  2. Truncate/pad the inconsistent tensor so shape[2] matches

Example fix

// before
cnt = torch.zeros((B,H,33), ...); idx = torch.zeros((B,H,32,N), ...)
// after
M = (seqlen_q + q_bs - 1) // q_bs
cnt = torch.zeros((B,H,M), ...); idx = torch.zeros((B,H,M,N), ...)
Defensive patterns

Strategy: validation

Validate before calling

assert mask_block_cnt.shape[2] == mask_block_idx.shape[2]

Prevention

When it happens

Trigger: 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).

Common situations: Building cnt and idx in separate code paths that rounded seqlen_q/block_size differently, or editing one tensor during debugging.

Related errors


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