jax-ml/jax · error · ValueError
must be a multiple of .
Error message
{bkv_compute=} must be a multiple of {NUM_LANES}. What it means
Validation in the splash attention forward kernel: bkv_compute (the per-computation KV block size) must be a multiple of NUM_LANES so the block maps evenly onto TPU lanes. Fires when bkv_compute % NUM_LANES != 0 (after checking bkv is a multiple of bkv_compute).
Solutions
- Set block_kv_compute to a multiple of 8 (64, 128, 256...)
- Use the library's default block size selection (block_sizes=None)
- Pin JAX to a version whose recommended block sizes you copied, or regenerate them with the current version's helper
Example fix
// before BlockSizes(block_kv=256, block_kv_compute=100) // after BlockSizes(block_kv=256, block_kv_compute=128)
Defensive patterns
Strategy: validation
Validate before calling
assert (block_sizes.block_kv_compute or 0) % 8 == 0
Type guard
def lane_aligned(x) -> bool: return x is None or x % 8 == 0
Prevention
- Keep every block size a multiple of 8
- Prefer library defaults (block_sizes=None)
When it happens
Trigger: block_sizes=BlockSizes(block_kv=128, block_kv_compute=100) — 128 % 8 == 0 but 100 % 8 != 0.
Common situations: Fine-tuning compute tiling for TPU v5e/v6e where smaller compute blocks improve pipelining; using legacy block sizes from before this constraint existed.
Related errors
- should be a multiple of
- must be a multiple of .
- must be a multiple of .
- should not be greater than
- block_kv must be a multiple of
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/d12e045497b30408.
Report an issue: GitHub.
Appendix: source
Thrown at jax/experimental/pallas/ops/tpu/splash_attention/splash_attention_kernel.py:971
)
if not is_mqa and num_q_heads % num_kv_heads != 0:
raise ValueError(
f"In MHA, expected number of 'key' heads ({num_kv_heads}) to be a"
f" multiple of the number of 'query' heads ({num_q_heads})"
)
if k.shape[:-1] != v.shape[:-1]:
raise ValueError(
f"Expected 'key' {k.shape} and 'value' {v.shape} to have the same "
"leading dimensions."
)
assert bkv_compute is not None
if bkv % bkv_compute:
raise ValueError(f"{bkv=} must be a multiple of {bkv_compute=}.")
if bkv_compute % NUM_LANES:
raise ValueError(f"{bkv_compute=} must be a multiple of {NUM_LANES}.")
kv_seq_len = k.shape[kv_seq_len_dimension]
q_heads_per_kv_head = num_q_heads // num_kv_heads
if segment_ids is not None:
if segment_ids.q.shape != (q_seq_len,):
raise ValueError(
"Invalid shape for q segment_ids: "
f"{segment_ids.q.shape}. Expected: {(q_seq_len,)}"
)
if segment_ids.kv.shape != (kv_seq_len,):
raise ValueError(
"Invalid shape for kv segment_ids: "
f"{segment_ids.kv.shape}. Expected: {(kv_seq_len,)}"
)
q_layout = block_sizes.q_layoutView on GitHub (pinned to 1e1c6a8fc0)