sgl-project/sglang · error · ValueError
Block sparse tensors{context} require explicit sparse_block_
Error message
Block sparse tensors{context} require explicit sparse_block_size[0] to disambiguate block size for seqlen_q={seqlen_q} and num_m_blocks={num_m_blocks}. What it means
Raised when sparse_block_size_q cannot be inferred: seqlen_q is divisible such that multiple q-block sizes could produce the observed num_m_blocks, and base_m_block != 1, so the layout is ambiguous. The user must pass sparse_block_size[0] explicitly.
Source
Thrown at python/sglang/kernels/ops/attention/flash_attn/cute/block_sparsity.py:348
"""
base_m_block = q_stage * m_block_size
base_n_block = n_block_size
if sparse_block_size_kv is None:
sparse_block_size_kv = base_n_block
if sparse_block_size_kv != base_n_block:
raise ValueError(
f"Block sparse tensors{context} require BLOCK_SIZE_KV={base_n_block}."
)
if tensors.mask_block_idx is None:
raise ValueError(
"mask_block_cnt and mask_block_idx must be provided for block sparsity."
)
num_m_blocks = tensors.mask_block_idx.shape[2]
if sparse_block_size_q is None:
sparse_block_size_q = get_sparse_q_block_size(tensors, seqlen_q)
if sparse_block_size_q is None and base_m_block != 1:
raise ValueError(
f"Block sparse tensors{context} require explicit sparse_block_size[0] "
f"to disambiguate block size for seqlen_q={seqlen_q} and num_m_blocks={num_m_blocks}."
)
if sparse_block_size_q is None:
sparse_block_size_q = ceildiv(seqlen_q, num_m_blocks)
if sparse_block_size_q % base_m_block != 0:
raise ValueError(
f"Block sparse tensors{context} have block size {sparse_block_size_q}, "
f"which must be a multiple of {base_m_block}."
)
expected_m_blocks = ceildiv(seqlen_q, sparse_block_size_q)
expected_n_blocks = ceildiv(seqlen_k, sparse_block_size_kv)
q_subtile_factor = sparse_block_size_q // base_m_block
expected_count_shape = (batch_size, num_head, expected_m_blocks)
expected_index_shape = (batch_size, num_head, expected_m_blocks, expected_n_blocks)
View on GitHub (pinned to 0132848349)
Solutions
- Pass sparse_block_size=(sparse_block_size_q, kv_size) explicitly to the op/normalize call
- Rebuild the BlockMask recording its q block size so it can be supplied later
Example fix
// before out = fa(q, k, v, block_sparse_tensors=tensors) // after out = fa(q, k, v, block_sparse_tensors=tensors, sparse_block_size=(128, 128))
Defensive patterns
Strategy: validation
Validate before calling
if seqlen_q % num_m_blocks == 0 and base_m_block != 1 and sparse_block_size_q is None:
sparse_block_size_q = seqlen_q // num_m_blocks # pass explicitly Prevention
- Always pass sparse_block_size explicitly when seqlen_q can vary
- Store the mask's q block size alongside the tensors
When it happens
Trigger: Calling normalize_block_sparse_config without sparse_block_size_q, with seqlen_q that doesn't unambiguously map to num_m_blocks (e.g. seqlen_q=4096, num_m_blocks=32 could be q-block 128) and kernel q_stage*m_block_size != 1.
Common situations: Dynamically-shaped workloads where seqlen_q varies and the block size was only implied by the mask construction.
Related errors
- {tensor_name}{context_clause} with shape {tensor.shape} cann
- {name}_block_cnt and {name}_block_idx must both be provided
- {name}_block tensors must have dtype torch.int32
- {name}_block_cnt and {name}_block_idx must be on the same de
- {name}_block tensors must live on CUDA
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/d2a1e9415d5eb445.
Report an issue: GitHub.