jax-ml/jax · error · ValueError

Cannot merge empty list of indexers

Error message

Cannot merge empty list of indexers

What it means

merge_indexers was called with an empty sequence of indexers while lowering chained getitem/setitem operations on references inside a Mosaic GPU kernel. It is an internal API contract violation; the public path always passes at least one indexer, so seeing it usually means an internal inconsistency or direct misuse of internals.

Source

Thrown at jax/_src/pallas/mosaic_gpu/lowering.py:4483

      return _as_index(v.registers.item())
    case jax_literals.TypedNdArray() if (
        np.issubdtype(v.dtype, np.integer) and v.ndim == 0
    ):
      return arith_dialect.constant(ir.IndexType.get(), int(v))
    case _:
      raise ValueError(f"Unsupported index: {v} of type {type(v)}")


def merge_indexers(
    indexers: Sequence[indexing.NDIndexer]) -> indexing.NDIndexer:
  """Merges multiple indexers into a single indexer.

  This function computes a new indexer such that applying the
  new indexer produces the same result as applying the sequence
  of input indexers in order from first-to-last.
  """
  if len(indexers) == 0:
    raise ValueError("Cannot merge empty list of indexers")
  if len(indexers) == 1:
    return indexers[0]
  root_shape = indexers[0].shape
  current_indices = [indexing.Slice(0, size, 1) for size in root_shape]
  removed_dimensions = set()
  for indexer in indexers:
    if indexer.int_indexer_shape:
      raise NotImplementedError()

    def _ensure_idx_fa(x: Any) -> mgpu.FragmentedArray:
      i32 = ir.IntegerType.get_signless(32)
      if isinstance(x, ir.Value):
        # TODO(cperivol): We assume all indices are signed. We should
        # look at the JAX avals to see if the integers are signed or
        # not to figure out is_signed.
        is_signed = False if isinstance(x.type, ir.IntegerType) else None
        return mgpu.FragmentedArray.splat(x, (), is_signed=is_signed).astype(
            i32, is_signed=False

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Pass at least one indexing.NDIndexer
  2. Check upstream logic that produced the empty list
Defensive patterns

Strategy: validation

Validate before calling

assert len(indexers) > 0

Prevention

When it happens

Trigger: Directly calling lowering.merge_indexers([]); or an internal lowering path where an indexer list was unexpectedly emptied by a transform.

Common situations: Rare; mostly seen by developers modifying JAX internals or building custom index flows.

Related errors


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