{"record":{"id":"1a14da376335cb4a","repo":"jax-ml/jax","slug":"reductions-require-axes-to-be-0-on-sparsecore","errorCode":null,"errorMessage":"reductions require axes to be (0,) on SparseCore, but got {axes}.","messagePattern":"reductions require axes to be \\(0,\\) on SparseCore, but got (.+?)\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"jax/_src/pallas/mosaic/sc_primitives.py","lineNumber":628,"sourceCode":"    )\n  if sign_bit_vec is not None:  # Flip the sign bit back\n    return arith.xori(result, sign_bit_vec)\n  return result\n\n\nsc_lowering.register_lowering_rule(masked_cummax_p)(\n    functools.partial(_masked_cumop_lowering_rule, reduction_kind=\"max\"))\nsc_lowering.register_lowering_rule(masked_cummin_p)(\n    functools.partial(_masked_cumop_lowering_rule, reduction_kind=\"min\"))\nsc_lowering.register_lowering_rule(masked_cumsum_p)(\n    functools.partial(_masked_cumop_lowering_rule, reduction_kind=\"sum\"))\n\n\ndef _reduce_op_lowering_rule(ctx: sc_lowering.LoweringRuleContext, x, axes,\n                             *, reduction_kind, out_sharding=None):\n  del out_sharding  # Unused.\n  if axes != (0,):\n    raise NotImplementedError(\n        f\"reductions require axes to be (0,) on SparseCore, but got {axes}.\")\n  vec_dim = ctx.avals_in[0].shape[0]\n  i1t = ir.IntegerType.get_signless(1)\n  c1 = arith.constant(i1t, ir.IntegerAttr.get(i1t, 1))\n  x_shp = ctx.avals_in[0].shape\n  c1v = vector.broadcast(ir.VectorType.get(x_shp, c1.type), c1)\n  return vector.extract(\n      _masked_cumop_lowering_rule(ctx, x, c1v, reduction_kind=reduction_kind),\n      [], [vec_dim - 1])\n\nsc_lowering.register_lowering_rule(\n    lax.reduce_max_p, kernel_types=[tpu_core.CoreType.SC_VECTOR_SUBCORE])(\n    functools.partial(_reduce_op_lowering_rule, reduction_kind=\"max\"))\nsc_lowering.register_lowering_rule(\n    lax.reduce_min_p, kernel_types=[tpu_core.CoreType.SC_VECTOR_SUBCORE])(\n    functools.partial(_reduce_op_lowering_rule, reduction_kind=\"min\"))\nsc_lowering.register_lowering_rule(\n    lax.reduce_sum_p, kernel_types=[tpu_core.CoreType.SC_VECTOR_SUBCORE])(","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/pallas/mosaic/sc_primitives.py#L610-L646","documentation":"SparseCore reduction lowering only supports reducing over axis 0 (the subcore's vector dimension). Reductions over any other axes tuple raise NotImplementedError.","triggerScenarios":"Binding a reduction primitive (sum/max/min over a BlockLayout array) with axes=(1,) or axes=(0,1) instead of (0,).","commonSituations":"Porting lax-style multi-axis reductions into an SC kernel; transposing data so the reduced dim is not axis 0.","solutions":["Transpose the array so the reduced dimension is axis 0, reduce, then transpose back if needed","Restructure to only reduce across the vector dimension","Compute multi-axis reductions as a sequence of axis-0 reductions"],"exampleFix":"// before\ny = sc_reduce(x, axes=(1,))\n\n// after\ny = sc_reduce(x.swapaxes(0, 1), axes=(0,))  # then swap result back as needed","handlingStrategy":"validation","validationCode":"assert axes == (0,), f'SparseCore reductions only support axes=(0,), got {axes}'","typeGuard":"def sc_reduce_axes_ok(axes) -> bool:\n    return tuple(axes) == (0,)","tryCatchPattern":null,"preventionTips":["Reduce only along the vector (axis 0) dimension","Transpose before/after for other layouts","Encapsulate reductions in an sc-aware helper"],"tags":["jax","pallas","sparsecore","reduction","axes"],"backgroundTag":"unsupported-reduction-axes","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}