jax-ml/jax · error · ValueError
axis_index_groups must all be the same size for TPU lowering
Error message
axis_index_groups must all be the same size for TPU lowering
What it means
On TPU, psum-family collectives with axis_index_groups lower to an AllReduce with explicit replica groups, which XLA requires to be uniformly sized. The lowering checks all groups share the same length before emitting HLO.
Solutions
- Pad or regroup axis_index_groups so every group has the same size
- Use equally-divisible mesh axis sizes
- Run on GPU/CPU if ragged grouping is semantically required
Example fix
// before lax.psum(x, 'i', axis_index_groups=[[0,1],[2]]) // after lax.psum(x, 'i', axis_index_groups=[[0,1],[2,3]])
Defensive patterns
Strategy: validation
Validate before calling
def check_groups(groups):
sizes = {len(g) for g in groups}
assert len(sizes) == 1, f'groups must be equally sized, got sizes {sizes}' Prevention
- Unit-test group size uniformity on TPU-targeted configs
When it happens
Trigger: Calling psum/pmax/pmin with axis_index_groups of unequal lengths while compiling for TPU.
Common situations: Handling a mesh whose axis size doesn't divide evenly into groups; code that worked on GPU (different lowering) failing on TPU.
Related errors
- run_scoped_p with collective axes is not supported
- Unsupported core type
- Acc ref dtype must be float32 or int32, got
- Acc ref must be at least 2D, got shape
- accessing .backend in multi-lowering setting. This can…
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/60e700b2cee96c72.
Report an issue: GitHub.
Appendix: source
Thrown at jax/_src/lax/parallel.py:1073
with ir.InsertionPoint.at_block_begin(ctx.module_context.module.body):
reducer = func_dialect.FuncOp(
f"{prim.name}_{scalar_aval.dtype}_reducer",
reducer_type,
)
reducer.attributes["sym_visibility"] = ir.StringAttr.get("private")
ctx.module_context.symbol_table.insert(reducer)
entry_block = reducer.add_entry_block()
_lower_reducer_into_block(ctx, prim, scalar_aval, entry_block)
return reducer
def _all_reduce_lowering(prim, pos_fn, ctx, arg, *, axes, axis_index_groups,
is_async=False):
aval_in, = ctx.avals_in
if axis_index_groups is not None and ("tpu" in ctx.module_context.platforms):
len_0 = len(axis_index_groups[0])
if any(len(g) != len_0 for g in axis_index_groups):
raise ValueError("axis_index_groups must all be the same size for TPU lowering")
named_axes, positional_axes = axes_partition = [], []
for axis in axes:
axes_partition[isinstance(axis, int)].append(axis)
if positional_axes:
reducer = mlir.lower_fun(pos_fn, multiple_results=False)
def _positional_reduce(aval, arg):
aval_out = aval.update(
shape=np.delete(np.array(aval.shape, dtype=np.int64),
positional_axes))
reducer_ctx = ctx.replace(primitive=None, avals_in=[aval], avals_out=[aval_out])
out, = reducer(reducer_ctx, arg, axes=tuple(positional_axes))
return out
arg = _positional_reduce(aval_in, arg)
if not named_axes:
return [arg]
replica_groups = _try_mesh_axes_replica_group(View on GitHub (pinned to 1e1c6a8fc0)