jax-ml/jax · error · ValueError
{x.shape=} does not match expected shape {expected_shape}
Error message
{x.shape=} does not match expected shape {expected_shape} What it means
Scatter's abstract eval computes the expected shape of the value from the ref shape and the indices (via _indexed_shape) and the provided value array x does not match. The value must exactly fill the region selected by the indices.
Source
Thrown at jax/_src/pallas/mosaic/sc_primitives.py:328
flat_args, tree = jax.tree.flatten((ref, transforms, indices, mask))
return gather_p.bind(*flat_args, tree=tree)
scatter_p = jax_core.Primitive("scatter")
scatter_p.is_effectful = lambda params: True
scatter_p.multiple_results = True
@scatter_p.def_effectful_abstract_eval
def _scatter_abstract_eval(*flat_args, tree, add):
ref, transforms, indices, x, mask = jax.tree.unflatten(tree, flat_args)
if transforms:
ref = state_types.TransformedRef(ref, transforms)
if ref.dtype not in (jnp.int32, jnp.float32):
raise TypeError(f"ref.dtype={ref.dtype} must be int32 or float32")
expected_shape = _indexed_shape(ref, indices)
if x.shape != expected_shape:
raise ValueError(
f"{x.shape=} does not match expected shape {expected_shape}"
)
if x.dtype != ref.dtype:
raise TypeError(f"val.dtype={x.dtype} != ref.dtype={ref.dtype}")
if mask is not None:
if mask.shape != expected_shape:
raise ValueError(
f"{mask.shape=} does not match expected shape {expected_shape}"
)
if mask.dtype != jnp.bool:
raise TypeError(f"Mask must be a boolean array, got {mask.dtype}")
effects: set[jax_core.Effect] = {state_types.WriteEffect(0)}
if add:
effects.add(state_types.ReadEffect(0))
return (), effects
@sc_lowering.register_lowering_rule(scatter_p)View on GitHub (pinned to 1e1c6a8fc0)
Solutions
- Print/inspect _indexed_shape(ref, indices) (shape arithmetic: ref shape minus indexed dims) and reshape x to match
- Fix the index shapes so the selected region matches x.shape
- Explicitly broadcast/reshape x before calling store_scatter/addupdate_scatter
Example fix
// before sc_primitives.store_scatter(ref, idx, x) # x.shape=(8, 32), expected=(8, 16) // after sc_primitives.store_scatter(ref, idx, x.reshape(8, 16)) # or fix idx/block shapes
Defensive patterns
Strategy: validation
Validate before calling
expected = _indexed_shape(ref, indices) # or reimplement: ref.shape minus indexed dims assert x.shape == expected, (x.shape, expected)
Type guard
def scatter_shapes_ok(ref, indices, x) -> bool:
indexed = sum(i.shape[-1] if hasattr(i, 'shape') else 1 for i in indices)
return tuple(x.shape) == tuple(ref.shape[indexed:]) Prevention
- Write shape preconditions next to each scatter call
- Print expected vs actual shapes in kernel debug runs
- Keep index count consistent with x's leading dims
When it happens
Trigger: Passing an x whose shape differs from _indexed_shape(ref, indices), e.g. indices of shape (N,) selecting rows of size M but x shaped (N, K) with K != M, or a mismatched leading dimension.
Common situations: Off-by-one in block sizes; broadcasting assumptions from NumPy that Pallas does not make; changing indices semantics (per-element vs per-slice) when porting code.
Related errors
- val.dtype={x.dtype} != ref.dtype={ref.dtype}
- {mask.shape=} does not match expected shape {expected_shape}
- Scatter only supports VectorSubcoreMesh, got {type(ref_aval.
- Scatter only supports storing to VMEM, got {memory_space}
- Indices must not be empty
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/8bec0fc3cabb5cd0.
Report an issue: GitHub.