jax-ml/jax · error · ValueError

Specified {device=} which requires a copy since the source d

Error message

Specified {device=} which requires a copy since the source device is {repr(dlpack_device)}, however copy=False. Set copy=True or copy=None to perform the requested operation.

What it means

In from_dlpack, the caller specified a target device that differs from the DLPack buffer's device; producing the array there requires a copy, but copy=False forbids it.

Source

Thrown at jax/_src/dlpack.py:180

    )
  elif max_version >= MIN_DLPACK_VERSION:
    # Oldest supported
    return _to_dlpack(
      x, stream=stream,
      src_device=src_device,
      device=device,
      copy=copy
    )
  else:
    raise BufferError(
      f"JAX does not support any version below {MIN_DLPACK_VERSION} but "
      f"version ({max_version}) was requested."
    )

def _check_device(device, dlpack_device, copy):
  if device and dlpack_device != device:
    if copy is not None and not copy:
      raise ValueError(
        f"Specified {device=} which requires a copy since the source device "
        f"is {repr(dlpack_device)}, however copy=False. Set copy=True or "
        "copy=None to perform the requested operation."
      )

def _place_array(_arr, device, dlpack_device, copy):
  if device and dlpack_device != device:
    return device_put(_arr, device)
  if copy:
    return jnp.array(_arr, copy=True)
  return _arr

def _is_tensorflow_tensor(external_array):
  t = type(external_array)
  return (
      t.__qualname__ == "EagerTensor"
      and t.__module__.endswith("tensorflow.python.framework.ops")
  )

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Set copy=True or copy=None to allow the transfer
  2. Use the external library to move the buffer first (e.g. tensor.to(device)) then from_dlpack with matching device
  3. Omit device to keep the array on the buffer's device and move later with jax.device_put

Example fix

# before
jax.dlpack.from_dlpack(t, device=jax.devices('gpu')[1], copy=False)

# after
jax.dlpack.from_dlpack(t, device=jax.devices('gpu')[1], copy=True)
Defensive patterns

Strategy: validation

Validate before calling

dl_dev = external.__dlpack_device__()  # compare via backend if needed
if device is not None and copy is False:
    # ensure device matches source, else allow copy
    copy = None

Try / catch

try:
    jax.dlpack.from_dlpack(t, device=dev, copy=False)
except ValueError:
    jax.dlpack.from_dlpack(t, device=dev, copy=True)

Prevention

When it happens

Trigger: jax.dlpack.from_dlpack(external, device=dev, copy=False) where dev != the external buffer's device reported by __dlpack_device__.

Common situations: Moving torch tensors from GPU 0 to a JAX array on GPU 1, or CPU->GPU, with zero-copy assumed in a multi-GPU training pipeline.

Related errors


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