{"record":{"id":"88e108bd6172beb0","repo":"deepset-ai/haystack","slug":"the-component-device-can-neither-be-empty-nor-cont","errorCode":null,"errorMessage":"The component device can neither be empty nor contain both a single device and a device map","messagePattern":"The component device can neither be empty nor contain both a single device and a device map","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/utils/device.py","lineNumber":307,"sourceCode":"\n    @classmethod\n    def from_multiple(cls, device_map: DeviceMap) -> \"ComponentDevice\":\n        \"\"\"\n        Create a component device representation from a device map.\n\n        :param device_map:\n            The device map.\n        :returns:\n            The component device representation.\n        \"\"\"\n        return cls(_multiple_devices=device_map)\n\n    def _validate(self) -> None:\n        \"\"\"\n        Validate the component device representation.\n        \"\"\"\n        if not (self._single_device is not None) ^ (self._multiple_devices is not None):\n            raise ValueError(\n                \"The component device can neither be empty nor contain both a single device and a device map\"\n            )\n\n    def to_torch(self) -> \"torch.device\":\n        \"\"\"\n        Convert the component device representation to PyTorch format.\n\n        Device maps are not supported.\n\n        :returns:\n            The PyTorch device representation.\n        \"\"\"\n        self._validate()\n\n        if self._single_device is None:\n            raise ValueError(\"Only single devices can be converted to PyTorch format\")\n\n        torch_import.check()","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/utils/device.py#L289-L325","documentation":"ComponentDevice._validate raises ValueError when the ComponentDevice is internally inconsistent: both _single_device and _multiple_devices are set, or neither is. A valid ComponentDevice must hold exactly one representation.","triggerScenarios":"Constructing ComponentDevice() directly with no arguments or with both single_device and multiple_devices set (e.g. via a custom from_* helper or __init__ misuse), or deserializing corrupted state; validation fires on any use (to_torch, to_hf, has_multiple_devices, etc.).","commonSituations":"Subclassing/constructing ComponentDevice by hand instead of using from_single/from_multiple/from_str; modifying private fields _single_device/_multiple_devices; loading a pickled component from an older incompatible version.","solutions":["Use the factory methods ComponentDevice.from_single, from_multiple, from_str, from_hf instead of direct construction","Set exactly one of _single_device/_multiple_devices if you must construct manually","Rebuild the ComponentDevice from a valid device string or map rather than mutating it"],"exampleFix":"// before\ncd = ComponentDevice()\ncd._single_device = dev; cd._multiple_devices = DeviceMap({\"0\": dev})  # invalid: both set\n// after\ncd = ComponentDevice.from_single(dev)\n# or cd = ComponentDevice.from_multiple(DeviceMap({\"0\": dev}))","handlingStrategy":"validation","validationCode":"def is_well_formed_component_device(cd: ComponentDevice) -> bool:\n    return (cd._single_device is not None) ^ (cd._multiple_devices is not None)","typeGuard":"def is_valid_component_device(cd: object) -> bool:\n    return isinstance(cd, ComponentDevice) and ((cd._single_device is None) != (cd._multiple_devices is None))","tryCatchPattern":"try:\n    cd.to_torch()\nexcept ValueError as e:\n    print(f\"ComponentDevice in invalid state: {e}\")","preventionTips":["Always build ComponentDevice via from_single/from_multiple/from_str/from_hf","Never assign _single_device/_multiple_devices directly","Discard and rebuild ComponentDevice from config instead of mutating loaded state"],"tags":["device","validation","state","value-error"],"backgroundTag":"invalid-device-configuration","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}