deepset-ai/haystack · error · ValueError

The component device can neither be empty nor contain both a

Error message

The component device can neither be empty nor contain both a single device and a device map

What it means

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.

Source

Thrown at haystack/utils/device.py:307

    @classmethod
    def from_multiple(cls, device_map: DeviceMap) -> "ComponentDevice":
        """
        Create a component device representation from a device map.

        :param device_map:
            The device map.
        :returns:
            The component device representation.
        """
        return cls(_multiple_devices=device_map)

    def _validate(self) -> None:
        """
        Validate the component device representation.
        """
        if not (self._single_device is not None) ^ (self._multiple_devices is not None):
            raise ValueError(
                "The component device can neither be empty nor contain both a single device and a device map"
            )

    def to_torch(self) -> "torch.device":
        """
        Convert the component device representation to PyTorch format.

        Device maps are not supported.

        :returns:
            The PyTorch device representation.
        """
        self._validate()

        if self._single_device is None:
            raise ValueError("Only single devices can be converted to PyTorch format")

        torch_import.check()

View on GitHub (pinned to e318778c9b)

Solutions

  1. Use the factory methods ComponentDevice.from_single, from_multiple, from_str, from_hf instead of direct construction
  2. Set exactly one of _single_device/_multiple_devices if you must construct manually
  3. Rebuild the ComponentDevice from a valid device string or map rather than mutating it

Example fix

// before
cd = ComponentDevice()
cd._single_device = dev; cd._multiple_devices = DeviceMap({"0": dev})  # invalid: both set
// after
cd = ComponentDevice.from_single(dev)
# or cd = ComponentDevice.from_multiple(DeviceMap({"0": dev}))
Defensive patterns

Strategy: validation

Validate before calling

def is_well_formed_component_device(cd: ComponentDevice) -> bool:
    return (cd._single_device is not None) ^ (cd._multiple_devices is not None)

Type guard

def is_valid_component_device(cd: object) -> bool:
    return isinstance(cd, ComponentDevice) and ((cd._single_device is None) != (cd._multiple_devices is None))

Try / catch

try:
    cd.to_torch()
except ValueError as e:
    print(f"ComponentDevice in invalid state: {e}")

Prevention

When it happens

Trigger: 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.).

Common situations: 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.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/88e108bd6172beb0. Report an issue: GitHub.