{"record":{"id":"cf9541eb4d14d8d0","repo":"jax-ml/jax","slug":"index-i-out-of-bounds-for-axis-axis-with-size","errorCode":null,"errorMessage":"index {i} out of bounds for axis {axis} with size {size} ({normalize_indices=})","messagePattern":"index (.+?) out of bounds for axis (.+?) with size (.+?) \\((.+?)\\)","errorType":"validation","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"jax/_src/numpy/indexing.py","lineNumber":214,"sourceCode":"    \"\"\"Create an NDIndexer object from raw user-supplied indices.\"\"\"\n    indices = eliminate_deprecated_list_indexing(indices)\n    parsed = _parse_indices(indices, shape)\n    return cls(shape=shape, indices=parsed)\n\n  def validate_static_indices(self, normalize_indices: bool = True) -> None:\n    \"\"\"Check that all static integer indices are in-bounds.\n\n    Raises an IndexError in case of out-of-bound indices\n    \"\"\"\n    for idx in self.indices:\n      if idx.typ == IndexType.INTEGER:\n        assert isinstance(idx.index, (int, np.integer))\n        i = operator.index(idx.index)\n        axis, = idx.consumed_axes\n        size = self.shape[axis]\n        normed_idx = i + size if normalize_indices and i < 0 else i\n        if not 0 <= normed_idx < size:\n          raise IndexError(f\"index {i} out of bounds for axis {axis} with size {size}\"\n                           f\" ({normalize_indices=})\")\n\n  def validate_slices(self) -> None:\n    \"\"\"Check that all slices have static start/stop/step values.\n\n    Raises an IndexError in case of non-static entries.\n    \"\"\"\n    for position, idx in enumerate(self.indices):\n      if idx.typ == IndexType.SLICE:\n        assert isinstance(idx.index, slice)\n        elts = [idx.index.start, idx.index.stop, idx.index.step]\n        if not all(_is_slice_element_none_or_constant_or_symbolic(val)\n                   for val in elts):\n          msg = (\"Array slice indices must have static start/stop/step to be used \"\n                 f\"with NumPy indexing syntax. Got {idx.index} at position \"\n                 f\"{position}. To index an array at a dynamic position with a \"\n                 \"static slice size, use x[jax.ds(start, size)] or \"\n                 \"lax.dynamic_slice/dynamic_update_slice instead (JAX does not \"","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/numpy/indexing.py#L196-L232","documentation":"validate_static_indices checks static integer indices against the array's static shape; after optional negative-index normalization, the index must satisfy 0 <= i < size for that axis. This check runs when mode='promise_in_bounds' paths (e.g. to_static_slice) validate user indices.","triggerScenarios":"x = jnp.zeros(3); x[5] or x[-4]; also x[3] on an axis whose size shrank after a reshape/config change. Raised in static-index validation during rewriting_take/to_static_slice.","commonSituations":"Off-by-one loop bounds, hardcoded index for a shape that changed (batch-size config), negative index equal to -size-1, or empty axis edge cases.","solutions":["Clamp or modulo the index: x[i % x.shape[0]]","Re-check the shape at runtime with x.shape[axis] before indexing","Fix off-by-one in loop ranges (range(n) vs range(n+1))"],"exampleFix":"// before\ny = x[i]  # i may equal n on last step\n// after\ny = x[min(i, x.shape[0] - 1)]","handlingStrategy":"validation","validationCode":"n = x.shape[axis]\ni = i + n if i < 0 else i\nassert 0 <= i < n, f'{i} not in [0,{n})'","typeGuard":null,"tryCatchPattern":"try:\n    y = x[i]\nexcept IndexError:\n    y = x[i % x.shape[0]]  # wrap-around fallback","preventionTips":["Normalize negative indices once at input boundaries","Add asserts in loops that index with computed values"],"tags":["jax","indexing","out-of-bounds"],"backgroundTag":"index-out-of-bounds","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}