{"record":{"id":"153ae55c55ac9458","repo":"jax-ml/jax","slug":"dynamic-slice-requires-mode-promise-in-bounds-or","errorCode":null,"errorMessage":"dynamic_slice requires mode='promise_in_bounds' or mode='clip'","messagePattern":"dynamic_slice requires mode='promise_in_bounds' or mode='clip'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/numpy/indexing.py","lineNumber":481,"sourceCode":"      rev_axes=rev_axes,\n      squeeze_axes=squeeze_axes,\n      newaxis_dims=newaxis_dims,\n    )\n\n  def to_dynamic_slice(\n      self, *,\n      arr_is_sharded: bool = False,\n      normalize_indices: bool = True,\n      mode: str | slicing.GatherScatterMode | None) -> _DynamicSliceIndexer:\n    \"\"\"Convert to DynamicSliceIndexer data structure.\n\n    If this is not possible, raise a ValueError, TypeError, or IndexError.\n    \"\"\"\n    if mode is not None:\n      parsed_mode = slicing.GatherScatterMode.from_any(mode)\n      if parsed_mode not in [\n          slicing.GatherScatterMode.PROMISE_IN_BOUNDS, slicing.GatherScatterMode.CLIP]:\n        raise ValueError(\"dynamic_slice requires mode='promise_in_bounds' or mode='clip'\")\n\n    # For sharded inputs, indexing (like x[0]) and partial slices (like x[:2] as\n    # opposed to x[:]) lead to incorrect sharding semantics when computed via slice.\n    # TODO(yashkatariya): fix slice with sharding\n    if arr_is_sharded and self.has_partial_slices():\n      raise ValueError(\"dynamic_slice with partial slices does not support nontrivial array sharding.\")\n\n    for position, pidx in enumerate(self.indices):\n      if pidx.typ in [IndexType.INTEGER, IndexType.ELLIPSIS, IndexType.NONE]:\n        pass\n      elif pidx.typ == IndexType.DYNAMIC_SLICE:\n        assert isinstance(pidx.index, indexing.Slice)\n        if pidx.index.stride != 1:\n          raise TypeError(\"dynamic_slice: only unit steps supported in slice.\"\n                          f\" Got {pidx.index} at position {position}\")\n      elif pidx.typ == IndexType.SLICE:\n        assert isinstance(pidx.index, slice)\n        if pidx.index.step is not None and pidx.index.step not in [-1, 1]:","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/numpy/indexing.py#L463-L499","documentation":"to_dynamic_slice mirrors to_static_slice's mode restriction: only PROMISE_IN_BOUNDS and CLIP are valid. Modes like DROP or FILL cannot be honored by lax.dynamic_slice, so passing them raises ValueError.","triggerScenarios":"Calling the dynamic-slice lowering with mode='drop' or ('fill', value) — e.g. jnp.take with mode='fill' on a path that lowers to dynamic_slice, or x[jax.ds(...)] with an incompatible mode kwarg.","commonSituations":"Copy-pasting mode='fill' from jnp.take calls into dynamic-slice-based code; configuring unique_indices/mode globally for gather semantics.","solutions":["Remove the mode kwarg (default promise_in_bounds)","Use mode='clip' to tolerate out-of-range dynamic starts","Use jnp.take/lax.gather if fill/drop semantics are required"],"exampleFix":"// before\ny = x[jax.ds(i, 5)]  # with mode='fill' configured\n// after\ny = x[jax.ds(i, 5)]  # default promise_in_bounds, ensure 0 <= i <= n-5","handlingStrategy":"validation","validationCode":"assert mode in (None, 'promise_in_bounds', 'clip') or mode is None","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use default mode for dynamic_slice paths","Switch to jnp.take(..., mode='fill') when fill semantics are needed"],"tags":["jax","dynamic-slice","mode","api-misuse"],"backgroundTag":"invalid-mode-argument","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}