jax-ml/jax · error · ValueError

reduction operation {self.__name__!r} does not have an ident

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.

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)

Solutions

  1. Pass an explicit initial value, e.g. jnp.maximum.reduce(x, where=mask, initial=-jnp.inf)
  2. 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

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


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/83652e5966e22aa0. Report an issue: GitHub.