{"record":{"id":"5c8351c539d08922","repo":"jax-ml/jax","slug":"an-index-can-only-have-a-single-ellipsis","errorCode":null,"errorMessage":"an index can only have a single ellipsis ('...')","messagePattern":"an index can only have a single ellipsis \\('\\.\\.\\.'\\)","errorType":"validation","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"jax/_src/numpy/indexing.py","lineNumber":161,"sourceCode":"    index_types.append(typ)\n\n    if typ == IndexType.NONE:\n      dimensions_consumed.append(0)\n    elif typ == IndexType.ELLIPSIS:\n      # We don't yet know how many dimensions are consumed, so set to zero\n      # for now and update later.\n      dimensions_consumed.append(0)\n      ellipses_indices.append(i)\n    elif typ == IndexType.BOOLEAN:\n      dimensions_consumed.append(np.ndim(idx))  # pyrefly: ignore[bad-argument-type]\n    elif typ in [IndexType.INTEGER, IndexType.ARRAY, IndexType.SLICE, IndexType.DYNAMIC_SLICE]:\n      dimensions_consumed.append(1)\n    else:\n      raise IndexError(f\"Unrecognized index type: {typ}\")\n\n  # 2. Validate the consumed dimensions and ellipses.\n  if len(ellipses_indices) > 1:\n    raise IndexError(\"an index can only have a single ellipsis ('...')\")\n  total_consumed = sum(dimensions_consumed)\n  if total_consumed > len(shape):\n    raise IndexError(f\"Too many indices: array is {len(shape)}-dimensional,\"\n                     f\" but {total_consumed} were indexed\")\n  if ellipses_indices:\n    dimensions_consumed[ellipses_indices[0]] = len(shape) - total_consumed\n\n  # 3. Generate the final sequence of parsed indices.\n  result: list[ParsedIndex] = []\n  current_dim = 0\n  for index, typ, n_consumed in safe_zip(indices, index_types, dimensions_consumed):\n    consumed_axes = tuple(range(current_dim, current_dim + n_consumed))\n    current_dim += len(consumed_axes)\n    result.append(ParsedIndex(index=index, typ=typ, consumed_axes=consumed_axes))\n  return result\n\n\n@register_pytree_node_class","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/numpy/indexing.py#L143-L179","documentation":"_parse_indices enforces that at most one ellipsis ('...') may appear in an index expression; a second ellipsis has no defined meaning. This mirrors NumPy's 'an index can only have a single ellipsis' error, raised while validating consumed dimensions.","triggerScenarios":"x[..., 0, ...] — two Ellipsis objects in one indexing expression.","commonSituations":"Programmatically concatenating index tuples that each already contain an ellipsis, or copy-pasting an ellipsis into an expression that already had one.","solutions":["Remove the extra ellipsis; use explicit slices (:) to skip axes","When building index tuples dynamically, track whether an ellipsis was already added","Replace ellipsis with slice(None) for full determinism"],"exampleFix":"// before\ny = x[..., 0, ...]\n// after\ny = x[..., 0]","handlingStrategy":"validation","validationCode":"idx = tuple(idx)\nassert sum(1 for i in idx if i is Ellipsis) <= 1, 'multiple ellipses'","typeGuard":"def has_single_ellipsis(idx_tuple) -> bool:\n    return sum(1 for i in idx_tuple if i is Ellipsis) <= 1","tryCatchPattern":null,"preventionTips":["When concatenating index tuples, dedupe ellipsis first","Prefer slice(None) over Ellipsis in generated code"],"tags":["jax","indexing","ellipsis"],"backgroundTag":"invalid-index-expression","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}