{"record":{"id":"4b660869e84fbfc4","repo":"jax-ml/jax","slug":"one-of-src-or-dst-must-be-a-bufferedref","errorCode":null,"errorMessage":"One of src or dst must be a BufferedRef.","messagePattern":"One of src or dst must be a BufferedRef\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/pallas/mosaic/pipeline.py","lineNumber":1665,"sourceCode":"      partition_dimension,\n      grid_offset,\n  )\n  return new_grid, offsets\n\n\ndef sync_copy(src: REF | BufferedRef, dst: REF | BufferedRef, indices):\n  \"\"\"Perform a synchronous copy from src to dst.\"\"\"\n  bref: BufferedRef\n  hbm_ref: REF\n  if isinstance(src, BufferedRef):\n    bref = src\n    if isinstance(dst, BufferedRef):\n      raise ValueError(\"Only one of src or dst can be a BufferedRef.\")\n    hbm_ref = dst\n    copy_in = False\n  else:\n    if not isinstance(dst, BufferedRef):\n      raise ValueError(\"One of src or dst must be a BufferedRef.\")\n    bref = dst\n    hbm_ref = src\n    copy_in = True\n  window_ref = bref.current_ref\n  if not bref.is_trivial_windowing:\n    hbm_slice = bref.get_dma_slice(_ref_to_value_aval(hbm_ref), indices)\n    bref_slice = bref._to_window_slice(hbm_slice)\n    hbm_ref = hbm_ref.at[hbm_slice]\n    window_ref = window_ref.at[bref_slice]\n  if copy_in:\n    tpu_helpers.sync_copy(hbm_ref, window_ref)\n  else:\n    tpu_helpers.sync_copy(window_ref, hbm_ref)\n\n\n@tree_util.register_pytree_node_class\n@dataclasses.dataclass(frozen=True, eq=False)\nclass PipelineStep:","sourceCodeStart":1647,"sourceCodeEnd":1683,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/pallas/mosaic/pipeline.py#L1647-L1683","documentation":"sync_copy requires that at least one endpoint be a BufferedRef (that's the whole point of a pipeline-memory copy). If neither src nor dst is a BufferedRef, there is nothing buffered to sync and this ValueError is raised.","triggerScenarios":"Calling sync_copy with two ordinary references/arrays, e.g. copying HBM-to-HBM or passing unwrapped Refs after a refactor removed the buffering spec.","commonSituations":"A spec that was expected to be pipelined silently became non-pipelined (e.g. trivial windowing made it a plain ref), then a copy helper is invoked on it; generic copy helper applied to non-pipeline tensors.","solutions":["Check that one endpoint actually carries pipeline_mode/buffering; if not, use ordinary ref.set / pallas copy instead of sync_copy","Verify the BufferedRef wasn't replaced by a plain ref by a trivial-windowing optimization","If both are plain refs, do the copy directly (dst[...] = src[...])"],"exampleFix":"# before\nsync_copy(plain_src_ref, plain_dst_ref)\n# after\nplain_dst_ref[...] = plain_src_ref[...]","handlingStrategy":"type-guard","validationCode":"assert isinstance(src, BufferedRef) or isinstance(dst, BufferedRef), \\\n    'sync_copy requires a BufferedRef endpoint'","typeGuard":"def has_bref(src, dst) -> bool:\n    return isinstance(src, BufferedRef) or isinstance(dst, BufferedRef)","tryCatchPattern":null,"preventionTips":["Use plain ref assignment for non-pipelined copies","Verify a spec's buffering wasn't optimized away before calling sync_copy helpers"],"tags":["jax","pallas","pipeline","copy"],"backgroundTag":"invalid-argument-type","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}