jax-ml/jax · error · IndexError

an index can only have a single ellipsis ('...')

Error message

an index can only have a single ellipsis ('...')

What it means

_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.

Source

Thrown at jax/_src/numpy/indexing.py:161

    index_types.append(typ)

    if typ == IndexType.NONE:
      dimensions_consumed.append(0)
    elif typ == IndexType.ELLIPSIS:
      # We don't yet know how many dimensions are consumed, so set to zero
      # for now and update later.
      dimensions_consumed.append(0)
      ellipses_indices.append(i)
    elif typ == IndexType.BOOLEAN:
      dimensions_consumed.append(np.ndim(idx))  # pyrefly: ignore[bad-argument-type]
    elif typ in [IndexType.INTEGER, IndexType.ARRAY, IndexType.SLICE, IndexType.DYNAMIC_SLICE]:
      dimensions_consumed.append(1)
    else:
      raise IndexError(f"Unrecognized index type: {typ}")

  # 2. Validate the consumed dimensions and ellipses.
  if len(ellipses_indices) > 1:
    raise IndexError("an index can only have a single ellipsis ('...')")
  total_consumed = sum(dimensions_consumed)
  if total_consumed > len(shape):
    raise IndexError(f"Too many indices: array is {len(shape)}-dimensional,"
                     f" but {total_consumed} were indexed")
  if ellipses_indices:
    dimensions_consumed[ellipses_indices[0]] = len(shape) - total_consumed

  # 3. Generate the final sequence of parsed indices.
  result: list[ParsedIndex] = []
  current_dim = 0
  for index, typ, n_consumed in safe_zip(indices, index_types, dimensions_consumed):
    consumed_axes = tuple(range(current_dim, current_dim + n_consumed))
    current_dim += len(consumed_axes)
    result.append(ParsedIndex(index=index, typ=typ, consumed_axes=consumed_axes))
  return result


@register_pytree_node_class

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Remove the extra ellipsis; use explicit slices (:) to skip axes
  2. When building index tuples dynamically, track whether an ellipsis was already added
  3. Replace ellipsis with slice(None) for full determinism

Example fix

// before
y = x[..., 0, ...]
// after
y = x[..., 0]
Defensive patterns

Strategy: validation

Validate before calling

idx = tuple(idx)
assert sum(1 for i in idx if i is Ellipsis) <= 1, 'multiple ellipses'

Type guard

def has_single_ellipsis(idx_tuple) -> bool:
    return sum(1 for i in idx_tuple if i is Ellipsis) <= 1

Prevention

When it happens

Trigger: x[..., 0, ...] — two Ellipsis objects in one indexing expression.

Common situations: Programmatically concatenating index tuples that each already contain an ellipsis, or copy-pasting an ellipsis into an expression that already had one.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/5c8351c539d08922. Report an issue: GitHub.