{"record":{"id":"12a93563af9efa66","repo":"jax-ml/jax","slug":"reduction-operation-name-does-not-have-an-identi","errorCode":null,"errorMessage":"reduction operation {name} does not have an identity, so to use a where mask one has to specify 'initial'","messagePattern":"reduction operation (.+?) does not have an identity, so to use a where mask one has to specify 'initial'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/numpy/reductions.py","lineNumber":121,"sourceCode":"               bool_op: ReductionOp | None = None,\n               upcast_f16_for_computation: bool = False,\n               axis: Axis = None, dtype: DTypeLike | None = None, out: None = None,\n               keepdims: bool = False, initial: ArrayLike | None = None,\n               where_: ArrayLike | None = None,\n               parallel_reduce: Callable[..., Array] | None = None,\n               promote_integers: bool = False) -> Array:\n  bool_op = bool_op or op\n  # Note: we must accept out=None as an argument, because numpy reductions delegate to\n  # object methods. For example `np.sum(x)` will call `x.sum()` if the `sum()` method\n  # exists, passing along all its arguments.\n  if out is not None:\n    raise NotImplementedError(f\"The 'out' argument to jnp.{name} is not supported.\")\n  a = ensure_arraylike(name, a)\n  where_ = check_where(name, where_)\n  axis = core.concrete_or_error(None, axis, f\"axis argument to jnp.{name}().\")\n\n  if initial is None and not has_identity and where_ is not None:\n    raise ValueError(f\"reduction operation {name} does not have an identity, so to use a \"\n                     f\"where mask one has to specify 'initial'\")\n\n  a = preproc(a) if preproc else a\n  pos_dims, dims = _reduction_dims(a, axis)\n\n  if initial is None and not has_identity:\n    shape = np.shape(a)\n    if not _all(shape[d] >= 1 for d in pos_dims):\n      raise ValueError(f\"zero-size array to reduction operation {name} which has no identity\")\n\n  result_dtype: DType\n  if dtype is None:\n    result_dtype = a.dtype\n    if promote_integers:\n      result_dtype = _promote_integer_dtype(result_dtype)\n  else:\n    result_dtype = dtypes.check_and_canonicalize_user_dtype(dtype, name)\n","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/numpy/reductions.py#L103-L139","documentation":"Reductions like max/min have no identity element (no neutral value for the operation), so when a where mask excludes every element along a reduction axis there is no defined result unless you supply an initial value.","triggerScenarios":"Calling jnp.max(x, where=mask) (or min) without initial; if the mask is all False along some axis the result is undefined, so JAX requires initial up front regardless of mask contents.","commonSituations":"Masked max/min aggregations (e.g. max over valid timesteps); porting numpy which returns garbage/NaN in this case; also triggered under jit where mask contents are unknown so the check is static.","solutions":["Supply an initial value: jnp.max(x, where=mask, initial=-jnp.inf)","Use jnp.where(mask, x, -jnp.inf).max(axis=...) to make the identity explicit","Switch to a reduction with identity (e.g. sum of where-filled values) if semantics allow"],"exampleFix":"// before\njnp.max(x, where=mask, axis=1)\n// after\njnp.max(x, where=mask, axis=1, initial=-jnp.inf)","handlingStrategy":"validation","validationCode":"jnp.max(x, where=mask, initial=-jnp.inf)  # always supply initial with where","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pair every where= in max/min with an initial=","Prefer where-filled arrays + plain max for clarity"],"tags":["jax","reductions","where-mask","identity"],"backgroundTag":"masked-reduction-without-initial","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}