jax-ml/jax · error · ValueError
reduction operation does not have an identity, so to use a…
Error message
reduction operation {self.__name__!r} does not have an identity, so to use a where mask one has to specify 'initial'. What it means
When reduce is called with a where mask, elements outside the mask are replaced by the operation's identity. If the ufunc has no identity (e.g. maximum over empty sets is undefined for some dtypes) and no initial value is given, the result is undefined, so JAX raises ValueError demanding an initial.
Solutions
- Pass an explicit initial value, e.g. jnp.maximum.reduce(x, where=mask, initial=-jnp.inf)
- If semantically valid, choose a ufunc that has an identity or compute the initial from your data's neutral element
Example fix
// before jnp.maximum.reduce(x, where=mask) // after jnp.maximum.reduce(x, where=mask, initial=-jnp.inf)
Defensive patterns
Strategy: validation
Validate before calling
if where is not None and ufunc.identity is None and initial is None:
raise ValueError('must pass initial for masked reduce without identity') Prevention
- Always pass initial when using where= masks with maximum/minimum-style reductions
When it happens
Trigger: jnp.maximum.reduce(x, where=mask) without initial for a ufunc whose identity is None.
Common situations: Masked reductions where all elements may be masked out; porting numpy where-masked reductions that relied on numpy's error semantics.
Related errors
- where argument must have dtype=bool; got dtype=
- out argument of .reduce()
- reduce only supported for binary ufuncs
- reduce only supported for functions returning a single value
- tuple of axes
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/83652e5966e22aa0.
Report an issue: GitHub.
Appendix: source
Thrown at jax/_src/numpy/ufunc_api.py:253
for example here is the reduction of :func:`jax.numpy.bitwise_or` along
the first axis of ``x``:
>>> jnp.bitwise_or.reduce(x, axis=1)
Array([3, 7], dtype=int32)
"""
check_arraylike(f"{self.__name__}.reduce", a)
if self.nin != 2:
raise ValueError("reduce only supported for binary ufuncs")
if self.nout != 1:
raise ValueError("reduce only supported for functions returning a single value")
if out is not None:
raise NotImplementedError(f"out argument of {self.__name__}.reduce()")
if initial is not None:
check_arraylike(f"{self.__name__}.reduce", initial)
if where is not None:
check_arraylike(f"{self.__name__}.reduce", where)
if self.identity is None and initial is None:
raise ValueError(f"reduction operation {self.__name__!r} does not have an identity, "
"so to use a where mask one has to specify 'initial'.")
if lax._dtype(where) != bool:
raise ValueError(f"where argument must have dtype=bool; got dtype={lax._dtype(where)}")
reduce = self.__static_props['reduce'] or self._reduce_via_scan
return reduce(a, axis=axis, dtype=dtype, keepdims=keepdims, initial=initial, where=where)
def _reduce_via_scan(self, arr: ArrayLike, axis: int | tuple[int, ...] | None = 0, dtype: DTypeLike | None = None,
keepdims: bool = False, initial: ArrayLike | None = None,
where: ArrayLike | None = None) -> Array:
assert self.nin == 2 and self.nout == 1
arr = lax.asarray(arr)
if initial is None:
initial = self.identity
if dtype is None:
dtype = api.eval_shape(self._func, lax._one(arr), lax._one(arr)).dtype
if where is not None:
where = _broadcast_to(where, arr.shape)
if isinstance(axis, tuple):View on GitHub (pinned to 1e1c6a8fc0)