{"record":{"id":"181a205bc382d7d9","repo":"xai-org/x-algorithm","slug":"execution-devices-must-be-a-list-of-xc-device-got","errorCode":null,"errorMessage":"execution_devices must be a list of xc.Device. Got: {execution_devices}","messagePattern":"execution_devices must be a list of xc\\.Device\\. Got: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"phoenix/xrex/utils/aot.py","lineNumber":216,"sourceCode":"    if compile_options is not None:\n        serialized_compile_options = compile_options.SerializeAsString()\n\n    with io.BytesIO() as file:\n        _JaxPjrtPickler(file, execution_devices).dump(unloaded_exec)\n        return PartiallySerialized(\n            file.getvalue(),\n            in_shardings_mem_kinds,\n            out_shardings_mem_kinds,\n            compiled._no_kwargs,\n            serialized_compile_options,\n        )\n\n\nclass _JaxPjrtPickler(pickle.Pickler):\n    def __init__(self, file, execution_devices: Sequence[xc.Device]):\n        super().__init__(file)\n        if not all(isinstance(d, xc.Device) for d in execution_devices):\n            raise ValueError(\n                f\"execution_devices must be a list of xc.Device. Got: {execution_devices}\"\n            )\n        self.device_to_index: dict[int, int] = {d.id: i for i, d in enumerate(execution_devices)}\n\n    def persistent_id(self, obj):\n        if isinstance(obj, xc.LoadedExecutable):\n            return (\"exec\", obj.client.serialize_executable(obj))\n        if isinstance(obj, xc._xla.Executable):\n            return (\"exec\", obj.serialize())\n        if isinstance(obj, xc.Device):\n            if obj.id not in self.device_to_index:\n                raise pickle.PicklingError(f\"Unknown device: {obj}\")\n            return (\"device\", self.device_to_index[obj.id])\n        if isinstance(obj, xc.Client):\n            return (\"client\",)\n        if is_host_callbacks(obj):\n            return (\"callbacks\",)\n        if isinstance(obj, xc.CompileOptions):","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/phoenix/xrex/utils/aot.py#L198-L234","documentation":"_JaxPjrtPickler replaces device objects with index references during pickling; it requires every element of execution_devices to be a jaxlib xla_extension (xc.Device) instance. Passing numpy objects, strings, ints, or devices from another abstraction raises this ValueError before pickling starts.","triggerScenarios":"Calling the AOT serialization path with execution_devices built from e.g. jax.devices() results mixed with None/int placeholders, or devices from a mock/stub in tests, or a plain list of device ids instead of Device objects.","commonSituations":"Test fixtures substituting fake devices; building the device list from device indices or platform strings; API changes where a helper starts returning device IDs rather than Device objects.","solutions":["Pass exactly the output of jax.devices() (or a slice of it) as execution_devices","Filter out non-Device entries before calling, e.g. [d for d in devices if isinstance(d, xc.Device)]","Fix upstream helpers that were returning device indices"],"exampleFix":"# before\nexecution_devices = [0, 1, 2, 3]\n# after\nimport jax\nexecution_devices = jax.devices()","handlingStrategy":"type-guard","validationCode":"from jax._src import xla_extension as xc\nassert all(isinstance(d, xc.Device) for d in execution_devices)","typeGuard":"def all_xc_devices(devs: Sequence) -> bool:\n    return all(isinstance(d, xc.Device) for d in devs)","tryCatchPattern":null,"preventionTips":["Always source execution_devices from jax.devices()","Never substitute ints/strings/mocks in production paths","Add a unit test that serialization runs with real jax.devices()"],"tags":["jax","type-validation","serialization"],"backgroundTag":"invalid-argument-type","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}