{"record":{"id":"a204760ba00957d8","repo":"jax-ml/jax","slug":"cannot-merge-empty-list-of-indexers","errorCode":null,"errorMessage":"Cannot merge empty list of indexers","messagePattern":"Cannot merge empty list of indexers","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/pallas/mosaic_gpu/lowering.py","lineNumber":4483,"sourceCode":"      return _as_index(v.registers.item())\n    case jax_literals.TypedNdArray() if (\n        np.issubdtype(v.dtype, np.integer) and v.ndim == 0\n    ):\n      return arith_dialect.constant(ir.IndexType.get(), int(v))\n    case _:\n      raise ValueError(f\"Unsupported index: {v} of type {type(v)}\")\n\n\ndef merge_indexers(\n    indexers: Sequence[indexing.NDIndexer]) -> indexing.NDIndexer:\n  \"\"\"Merges multiple indexers into a single indexer.\n\n  This function computes a new indexer such that applying the\n  new indexer produces the same result as applying the sequence\n  of input indexers in order from first-to-last.\n  \"\"\"\n  if len(indexers) == 0:\n    raise ValueError(\"Cannot merge empty list of indexers\")\n  if len(indexers) == 1:\n    return indexers[0]\n  root_shape = indexers[0].shape\n  current_indices = [indexing.Slice(0, size, 1) for size in root_shape]\n  removed_dimensions = set()\n  for indexer in indexers:\n    if indexer.int_indexer_shape:\n      raise NotImplementedError()\n\n    def _ensure_idx_fa(x: Any) -> mgpu.FragmentedArray:\n      i32 = ir.IntegerType.get_signless(32)\n      if isinstance(x, ir.Value):\n        # TODO(cperivol): We assume all indices are signed. We should\n        # look at the JAX avals to see if the integers are signed or\n        # not to figure out is_signed.\n        is_signed = False if isinstance(x.type, ir.IntegerType) else None\n        return mgpu.FragmentedArray.splat(x, (), is_signed=is_signed).astype(\n            i32, is_signed=False","sourceCodeStart":4465,"sourceCodeEnd":4501,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/pallas/mosaic_gpu/lowering.py#L4465-L4501","documentation":"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.","triggerScenarios":"Directly calling lowering.merge_indexers([]); or an internal lowering path where an indexer list was unexpectedly emptied by a transform.","commonSituations":"Rare; mostly seen by developers modifying JAX internals or building custom index flows.","solutions":["Pass at least one indexing.NDIndexer","Check upstream logic that produced the empty list"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"assert len(indexers) > 0","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat merge_indexers as internal API; don't call directly"],"tags":["pallas","internal-api","indexing"],"backgroundTag":"empty-collection-argument","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}