{"record":{"id":"c1b1f0a5d3ecdca0","repo":"jax-ml/jax","slug":"can-t-make-a-multicast-reference-into-a-peer-refer","errorCode":null,"errorMessage":"Can't make a multicast reference into a peer reference.","messagePattern":"Can't make a multicast reference into a peer reference\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/pallas/mosaic_gpu/core.py","lineNumber":1056,"sourceCode":"\n  def commute_ndindexer(\n      self, _: jax_core.AbstractValue, indexer: indexing.NDIndexer\n  ) -> tuple[indexing.NDIndexer, MulticastRef]:\n    return indexer, self\n\n\ndef remote_ref(\n    ref: _Ref,\n    device_id: jax.typing.ArrayLike,\n    device_id_type: pallas_primitives.DeviceIdType = pallas_primitives.DeviceIdType.MESH,\n) -> pallas_core.TransformedRef:\n  \"\"\"Translate memref to a symmetric memref on a peer device.\"\"\"\n  if not isinstance(ref, pallas_core.TransformedRef):\n    if not isinstance(jax_core.typeof(ref), state_types.AbstractRef):\n      raise TypeError(\"ref must be a reference\")\n    ref = pallas_core.TransformedRef(ref, transforms=())\n  if any(isinstance(t, MulticastRef) for t in ref.transforms):\n    raise ValueError(\"Can't make a multicast reference into a peer reference.\")\n  return pallas_core.TransformedRef(\n      ref.ref, (*ref.transforms, PeerMemRef(device_id, device_id_type)),\n  )\n\n\n@tree_util.register_dataclass\n@dataclasses.dataclass(frozen=True)\nclass ClusterRefTransform(state_types.Transform):\n  dims: tuple[jax_core.AxisName, ...] = jax.tree.static()\n  idxs: tuple[Any, ...]\n\n  def __post_init__(self):\n    if len(self.dims) != len(self.idxs):\n      raise ValueError(\"dims and idxs must have the same length\")\n\n  def transform_type(self, x):\n    return x\n","sourceCodeStart":1038,"sourceCodeEnd":1074,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/pallas/mosaic_gpu/core.py#L1038-L1074","documentation":"remote_ref refuses to wrap a reference that already contains a MulticastRef transform, because a reference cannot be both multicast (fan-out to multiple devices) and a peer (single remote device) simultaneously.","triggerScenarios":"Calling remote_ref(multicast_ref(...)) or composing multicast_ref then remote_ref on the same reference in a collective kernel.","commonSituations":"Writing TPU collective kernels that mix multicast stores and peer-device access on the same output ref.","solutions":["Apply remote_ref to the underlying ref before adding multicast, or use separate refs","Don't compose MulticastRef and PeerMemRef on the same reference; split stores across distinct refs","Reorder the store logic: do the peer store and multicast store on different references"],"exampleFix":"// before\nm = multicast_ref(out_ref, 'x')\np = remote_ref(m, 1)\n\n// after\np = remote_ref(out_ref, 1)\nm = multicast_ref(out_ref, 'x')","handlingStrategy":"validation","validationCode":"assert not any(isinstance(t, MulticastRef) for t in ref.transforms), 'already multicast'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never compose remote_ref with multicast_ref on the same reference"],"tags":["jax","pallas","mosaic-gpu","peer-memory","multicast"],"backgroundTag":"conflicting-reference-transforms","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}