{"record":{"id":"c172da4af925e6dc","repo":"jax-ml/jax","slug":"mask-shape-does-not-match-expected-shape-expec","errorCode":null,"errorMessage":"{mask.shape=} does not match expected shape {expected_shape}","messagePattern":"(.+?) does not match expected shape (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/pallas/mosaic/sc_primitives.py","lineNumber":335,"sourceCode":"\n\n@scatter_p.def_effectful_abstract_eval\ndef _scatter_abstract_eval(*flat_args, tree, add):\n  ref, transforms, indices, x, mask = jax.tree.unflatten(tree, flat_args)\n  if transforms:\n    ref = state_types.TransformedRef(ref, transforms)\n  if ref.dtype not in (jnp.int32, jnp.float32):\n    raise TypeError(f\"ref.dtype={ref.dtype} must be int32 or float32\")\n  expected_shape = _indexed_shape(ref, indices)\n  if x.shape != expected_shape:\n    raise ValueError(\n        f\"{x.shape=} does not match expected shape {expected_shape}\"\n    )\n  if x.dtype != ref.dtype:\n    raise TypeError(f\"val.dtype={x.dtype} != ref.dtype={ref.dtype}\")\n  if mask is not None:\n    if mask.shape != expected_shape:\n      raise ValueError(\n          f\"{mask.shape=} does not match expected shape {expected_shape}\"\n      )\n    if mask.dtype != jnp.bool:\n      raise TypeError(f\"Mask must be a boolean array, got {mask.dtype}\")\n  effects: set[jax_core.Effect] = {state_types.WriteEffect(0)}\n  if add:\n    effects.add(state_types.ReadEffect(0))\n  return (), effects\n\n\n@sc_lowering.register_lowering_rule(scatter_p)\ndef _scatter_lowering_rule(\n    ctx: sc_lowering.LoweringRuleContext, *flat_args, tree, add\n):\n  ref, transforms, indices, x, mask = jax.tree.unflatten(tree, flat_args)\n  ref_aval, *_ = tree.unflatten(ctx.avals_in)\n  if isinstance(ref_aval.memory_space, pallas_core.CoreMemorySpace):\n    if not isinstance(ref_aval.memory_space.mesh, sc_core.VectorSubcoreMesh):","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/pallas/mosaic/sc_primitives.py#L317-L353","documentation":"When an optional mask is given to scatter, its shape must equal the expected indexed shape (same as the value x). A mask of any other shape is rejected.","triggerScenarios":"Passing a mask broadcastable to (but not equal to) the selected region, e.g. mask of shape (N,1) while the region is (N,M), or a scalar/all-ones mask with wrong dims.","commonSituations":"Reusing a padding mask computed elsewhere with different axes kept; assuming NumPy broadcasting rules apply.","solutions":["Reshape/broadcast the mask explicitly to expected_shape before the call","If all elements should be written, pass mask=None","Recompute the mask inside the kernel from indices if shapes differ"],"exampleFix":"// before\nsc_primitives.store_scatter(ref, idx, x, mask=m)  # m.shape=(N,1)\n\n// after\nm = jnp.broadcast_to(m, x.shape)\nsc_primitives.store_scatter(ref, idx, x, mask=m)","handlingStrategy":"validation","validationCode":"if mask is not None:\n    assert mask.shape == x.shape, (mask.shape, x.shape)\n    mask = jnp.broadcast_to(mask, x.shape)","typeGuard":"def mask_shape_ok(mask, x) -> bool:\n    return mask is None or tuple(mask.shape) == tuple(x.shape)","tryCatchPattern":null,"preventionTips":["Normalize masks with broadcast_to at creation","Pass mask=None when storing everything","Keep mask generation adjacent to the value it masks"],"tags":["jax","pallas","sparsecore","scatter","mask-shape"],"backgroundTag":"shape-mismatch-scatter","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}