{"record":{"id":"ef8a37a0696982a1","repo":"jax-ml/jax","slug":"reduce-only-supported-for-binary-ufuncs","errorCode":null,"errorMessage":"reduce only supported for binary ufuncs","messagePattern":"reduce only supported for binary ufuncs","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/numpy/ufunc_api.py","lineNumber":243,"sourceCode":"\n      Similarly, :meth:`jax.numpy.logical_and.reduce` is equivalent to\n      :func:`jax.numpy.all`:\n\n      >>> jnp.logical_and.reduce(x > 2)\n      Array([False, False,  True], dtype=bool)\n      >>> jnp.all(x > 2, axis=0)\n      Array([False, False,  True], dtype=bool)\n\n      Some reductions do not correspond to any built-in aggregation function;\n      for example here is the reduction of :func:`jax.numpy.bitwise_or` along\n      the first axis of ``x``:\n\n      >>> jnp.bitwise_or.reduce(x, axis=1)\n      Array([3, 7], dtype=int32)\n    \"\"\"\n    check_arraylike(f\"{self.__name__}.reduce\", a)\n    if self.nin != 2:\n      raise ValueError(\"reduce only supported for binary ufuncs\")\n    if self.nout != 1:\n      raise ValueError(\"reduce only supported for functions returning a single value\")\n    if out is not None:\n      raise NotImplementedError(f\"out argument of {self.__name__}.reduce()\")\n    if initial is not None:\n      check_arraylike(f\"{self.__name__}.reduce\", initial)\n    if where is not None:\n      check_arraylike(f\"{self.__name__}.reduce\", where)\n      if self.identity is None and initial is None:\n        raise ValueError(f\"reduction operation {self.__name__!r} does not have an identity, \"\n                         \"so to use a where mask one has to specify 'initial'.\")\n      if lax._dtype(where) != bool:\n        raise ValueError(f\"where argument must have dtype=bool; got dtype={lax._dtype(where)}\")\n    reduce = self.__static_props['reduce'] or self._reduce_via_scan\n    return reduce(a, axis=axis, dtype=dtype, keepdims=keepdims, initial=initial, where=where)\n\n  def _reduce_via_scan(self, arr: ArrayLike, axis: int | tuple[int, ...] | None = 0, dtype: DTypeLike | None = None,\n                       keepdims: bool = False, initial: ArrayLike | None = None,","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/numpy/ufunc_api.py#L225-L261","documentation":"ufunc.reduce (e.g. jnp.add.reduce) generalizes reduction over a binary operation, so it requires a ufunc with exactly two inputs (nin == 2). Calling .reduce on a unary ufunc such as jnp.negative raises this ValueError.","triggerScenarios":"jnp.negative.reduce(x) or any unary/generic ufunc's .reduce method.","commonSituations":"Dynamic code that calls .reduce on an arbitrary ufunc object; assuming all numpy ufuncs support reduce.","solutions":["Only call .reduce on binary ufuncs (add, multiply, bitwise_or, maximum, ...)","For unary or non-reducible ops, express the reduction differently (e.g. use jnp.sum, jnp.prod)"],"exampleFix":"// before\njnp.negative.reduce(x)\n// after\n-jnp.sum(x)","handlingStrategy":"validation","validationCode":"assert ufunc.nin == 2, f'{ufunc.__name__} is not binary'","typeGuard":"def is_binary_ufunc(u): return u.nin == 2","tryCatchPattern":null,"preventionTips":["Prefer the named reductions (jnp.sum, jnp.prod) over generic ufunc.reduce"],"tags":["jax","ufunc","reduce","api-misuse"],"backgroundTag":"unsupported-reduce-operation","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}