jax-ml/jax · error · ValueError
Not implemented: {num_combined_kv_heads=} can not be XLA ful
Error message
Not implemented: {num_combined_kv_heads=} can not be XLA fully tiled. What it means
In get_min_heads_per_blk (used by ragged_paged_attention), the number of combined KV heads (K and V heads packed together, typically 2 * num_kv_heads) must be XLA-tileable: after dividing by the KV packing factor it must be 1, 2, 4, 8, or a multiple of 8. This is a kernel implementation restriction (see the TODO) — non-conforming head counts are not yet supported.
Source
Thrown at jax/experimental/pallas/ops/tpu/ragged_paged_attention/kernel.py:697
bits = dtypes.itemsize_bits(dtype)
return 32 // bits
def get_min_heads_per_blk(
num_q_heads, num_combined_kv_heads, q_dtype, kv_dtype
):
q_packing = get_dtype_packing(q_dtype)
kv_packing = get_dtype_packing(kv_dtype)
def can_be_xla_fully_tiled(x, packing):
if x % packing != 0:
return False
x //= packing
return x in (1, 2, 4, 8) or x % 8 == 0
# TODO(jevinjiang): support unaligned number of heads!
if not can_be_xla_fully_tiled(num_combined_kv_heads, kv_packing):
raise ValueError(
f"Not implemented: {num_combined_kv_heads=} can not be XLA fully tiled."
)
assert num_combined_kv_heads % 2 == 0
num_kv_heads = num_combined_kv_heads // 2
assert num_q_heads % num_kv_heads == 0
ratio = num_q_heads // num_kv_heads
# TODO(jevinjiang): we can choose smaller tiling for packed type if large
# second minor tiling is not on.
max_combined_kv_tiling = 8 * kv_packing
min_combined_kv_heads = (
max_combined_kv_tiling
if num_combined_kv_heads % max_combined_kv_tiling == 0
else num_combined_kv_heads
)
min_q_heads = min_combined_kv_heads // 2 * ratio
if can_be_xla_fully_tiled(min_q_heads, q_packing):
return min_q_heads, min_combined_kv_heads
return num_q_heads, num_combined_kv_headsView on GitHub (pinned to 1e1c6a8fc0)
Solutions
- Choose a KV head count such that num_combined_kv_heads // kv_packing is 1, 2, 4, 8, or a multiple of 8 (e.g. 4 or 8 KV heads)
- Pad/repeat KV heads to a supported count (jnp.repeat along the head axis) as a workaround
- Fall back to a non-Pallas attention implementation until unaligned head counts are supported
Example fix
// before
k, v have 6 heads each -> num_combined_kv_heads=12, not tileable
// after
# repeat to 8 kv heads
k = jnp.repeat(k, 2, axis=1); v = jnp.repeat(v, 2, axis=1) # adjust q head ratio accordingly
# or use a supported config (num_kv_heads in {1,2,4,8,16,...}) Defensive patterns
Strategy: validation
Validate before calling
def heads_tileable(num_combined_kv_heads, kv_packing):
x = num_combined_kv_heads
while x % 2 == 0 and (x // kv_packing) * kv_packing != x:
break
x = num_combined_kv_heads // kv_packing
return x in (1, 2, 4, 8) or x % 8 == 0
assert heads_tileable(2 * num_kv_heads, kv_packing) Try / catch
try:
ragged_paged_attention(...)
except ValueError as e:
if 'fully tiled' in str(e):
attention = fallback_standard_attention # non-Pallas path
else:
raise Prevention
- Stick to KV head counts of 1,2,4,8,16...
- Keep a fallback attention implementation for unsupported head layouts
When it happens
Trigger: Using KV head counts where 2*num_kv_heads / kv_packing is not in {1,2,4,8} or a multiple of 8, e.g. 6 KV heads with packing 1 (x=12 fails), or 12, 24 combined heads in some packing configurations.
Common situations: Running models with unusual GQA head counts (3, 6, 12 KV heads) on this TPU path; changing kv_paging/kernel version where the tiling rule changed.
Related errors
- masked load_p
- run_scoped_p with collective axes is not supported
- Non-decrementing wait is not supported.
- Only take_along_axis-like gathers supported
- Unsupported gather
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/c07063190faf3a2c.
Report an issue: GitHub.