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
- Rename images before constructing the dataset so every basename is unique — e.g. prefix with the subfolder or dataset name.
- Reconstruct the dataset with unique keys: rename files on disk or rewrite the image_paths/annotations dict keys.
- 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
- Rename images to globally unique basenames when merging datasets from different folders.
- Remember the check is case-insensitive — 'A.jpg' and 'a.jpg' collide.
- Run validate_image_paths yourself before long export jobs.
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
- Detections must have class_id attribute.
- Detections class_id must be a subset of source_to_target_map
- Class {class_name} not found in target classes. source_class
- The keys of the images and annotations dictionaries must mat
- Image paths {duplicates} are not unique across datasets.
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/50505548bbe68f40.
Report an issue: GitHub.