roboflow/supervision · error · ValueError

Cannot export dataset: image paths {first_path} and {image_p

Error message

Cannot export dataset: image paths {first_path} and {image_path} both map to {output_kind} file {first_name}. Ensure all image basenames are unique before exporting.

What it means

Raised by validate_image_paths (used by dataset exporters) when two different image paths produce the same output filename key in a case-insensitive sense (casefold is applied before duplicate detection). Exporters write one annotation/label file per image basename, so duplicate basenames — including 'A.jpg' vs 'a.jpg' on case-insensitive filesystems — would silently overwrite each other.

Source

Thrown at src/supervision/dataset/utils.py:185

        ```pycon
        >>> from pathlib import Path
        >>> from supervision.dataset.utils import check_no_basename_collisions
        >>> check_no_basename_collisions(
        ...     ["a/img.jpg", "b/img.jpg"], lambda p: Path(p).name, "image"
        ... )
        Traceback (most recent call last):
        ...
        ValueError: Cannot export dataset: image paths 'a/img.jpg' and ...

        ```
    """
    seen: dict[str, tuple[str, str]] = {}  # casefold(key) → (original name, image_path)
    for image_path in image_paths:
        output_name = key(image_path)
        case_key = output_name.casefold()
        if case_key in seen:
            first_name, first_path = seen[case_key]
            raise ValueError(
                f"Cannot export dataset: image paths {first_path!r} and "
                f"{image_path!r} both map to {output_kind} file {first_name!r}. "
                "Ensure all image basenames are unique before exporting."
            )
        seen[case_key] = (output_name, image_path)


def save_dataset_images(
    dataset: DetectionDataset,
    images_directory_path: str,
    show_progress: bool = False,
) -> None:
    """Save all images from a dataset to a directory.

    Images already in memory are written with ``cv2.imwrite``; images stored
    only as file paths are copied with ``shutil.copyfile``.

    Args:

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Rename images before constructing the dataset so every basename is unique — e.g. prefix with the subfolder or dataset name.
  2. Reconstruct the dataset with unique keys: rename files on disk or rewrite the image_paths/annotations dict keys.
  3. Export each source dataset to a separate output directory instead of merging first.

Example fix

// before
ds = DetectionDataset(classes=c, images=['a/img.jpg', 'b/img.jpg'], annotations=ann)
ds.as_yolo(...)  # ValueError: duplicate basenames

// after
import shutil
for i, p in enumerate(ds.image_paths):
    new_p = str(Path(out_dir) / f'{i:05d}_{Path(p).name}')
    shutil.copy(p, new_p)
    ds.annotations[new_p] = ds.annotations.pop(p)
    ds.image_paths[ds.image_paths.index(p)] = new_p
ds.as_yolo(...)
Defensive patterns

Strategy: validation

Validate before calling

keys = {Path(p).stem.casefold() for p in ds.image_paths}
if len(keys) != len(ds.image_paths):
    raise ValueError("Duplicate image basenames — rename before export")
ds.as_yolo(...)

Type guard

def unique_basenames(paths: list[str]) -> bool:
    stems = [Path(p).stem.casefold() for p in paths]
    return len(stems) == len(set(stems))

Prevention

When it happens

Trigger: Exporting a DetectionDataset containing both 'train/img.jpg' and 'val/img.jpg' (same basename, different directories) to YOLO/VOC/COCO via as_yolo/as_voc; also 'IMG.jpg' and 'img.jpg' colliding after casefold.

Common situations: Merging datasets that each have their own 'image_0001.jpg'; downloading datasets whose train/val folders reuse filenames; exporting on macOS/Windows where the filesystem itself is case-insensitive.

Related errors


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