roboflow/supervision · error · ValueError

Merging lazy and in-memory DetectionDatasets is not supporte

Error message

Merging lazy and in-memory DetectionDatasets is not supported.

What it means

Raised by DetectionDataset.merge() when the input datasets mix storage modes: some hold images in memory (dict of np.ndarray, or zero paths meaning fully in-memory) and some are lazy (paths only). Merge cannot produce a single consistent dataset from both modes, so it refuses rather than silently loading or dropping data.

Source

Thrown at src/supervision/dataset/core.py:335

            >>> ds_merged = sv.DetectionDataset.merge([ds_1, ds_2])
            >>> len(ds_merged)
            2
            >>> ds_merged.classes
            ['cat', 'dog', 'person']

            ```
        """

        def is_in_memory(dataset: DetectionDataset) -> bool:
            return len(dataset._images_in_memory) > 0 or len(dataset.image_paths) == 0

        def is_lazy(dataset: DetectionDataset) -> bool:
            return len(dataset._images_in_memory) == 0

        all_in_memory = all([is_in_memory(dataset) for dataset in dataset_list])
        all_lazy = all([is_lazy(dataset) for dataset in dataset_list])
        if not all_in_memory and not all_lazy:
            raise ValueError(
                "Merging lazy and in-memory DetectionDatasets is not supported."
            )

        images_in_memory = {}
        for dataset in dataset_list:
            images_in_memory.update(dataset._images_in_memory)

        image_paths = list(
            chain.from_iterable(dataset.image_paths for dataset in dataset_list)
        )
        image_paths_unique = list(dict.fromkeys(image_paths))
        if len(image_paths) != len(image_paths_unique):
            duplicates = find_duplicates(image_paths)
            raise ValueError(
                f"Image paths {duplicates} are not unique across datasets."
            )
        image_paths = image_paths_unique

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Convert everything to path-based (lazy) datasets: pass a list of image paths to all constructors.
  2. If memory allows, load all datasets with in-memory dict images so all are in-memory — though note dict-images are deprecated in 0.30.0.
  3. Merge only same-mode datasets and handle the other with a separate dataset object.

Example fix

// before
merged = DetectionDataset.merge([ds_dict_images, ds_path_list])  # mixed modes

// after
# normalize all to lazy path-based datasets
merged = DetectionDataset.merge([ds_a, ds_b])  # both built with images=[...paths...]
Defensive patterns

Strategy: validation

Validate before calling

modes = {"in_memory" if len(ds._images_in_memory) > 0 or len(ds.image_paths) == 0 else "lazy" for ds in dataset_list}
assert len(modes) == 1, f"Cannot merge mixed dataset modes: {modes}"
merged = DetectionDataset.merge(dataset_list)

Type guard

def all_lazy(datasets: list[DetectionDataset]) -> bool:
    return all(len(ds._images_in_memory) == 0 for ds in datasets)

Prevention

When it happens

Trigger: Calling DetectionDataset.merge([ds_in_memory, ds_lazy]) where ds_in_memory was built with images={'a.jpg': array} and ds_lazy with images=['b.jpg']. The internal is_in_memory/is_lazy predicates disagree across the list, so neither all_in_memory nor all_lazy holds.

Common situations: Merging a small hand-loaded dataset (arrays in memory) with a large disk-backed one; migrating old code that passed dict images (deprecated since 0.30.0) while new code passes path lists.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/4bf0a3e714eb32e4. Report an issue: GitHub.