roboflow/supervision · error · ValueError

COCO annotation file contains duplicate entries for image {i

Error message

COCO annotation file contains duplicate entries for image {image_name}. Each image must appear at most once.

What it means

Raised by load_coco_annotations when two entries in the images array resolve to the same canonical path, detected via the annotations dict keyed by resolved image_path. COCO requires each image to appear exactly once; duplicates would silently overwrite each other's Detections.

Source

Thrown at src/supervision/dataset/formats/coco.py:554

                f"resolves to the images directory itself "
                f"({images_directory_resolved}). Expected a path to an "
                "image file."
            )
        if images_directory_resolved not in resolved_image_path.parents:
            raise ValueError(
                f"COCO annotation refers to image {image_name!r}, which "
                f"resolves to {resolved_image_path} — outside the images "
                f"directory {images_directory_resolved}."
            )
        if resolved_image_path.is_dir():
            raise ValueError(
                f"COCO annotation refers to image {image_name!r}, which "
                f"resolves to directory {resolved_image_path}. Expected a "
                "path to an image file."
            )
        image_path = str(resolved_image_path)
        if image_path in annotations:
            raise ValueError(
                f"COCO annotation file contains duplicate entries for image "
                f"{image_name!r}. Each image must appear at most once."
            )

        with_masks = force_masks or any(
            _with_seg_mask(annotation) for annotation in image_annotations
        )
        annotation = coco_annotations_to_detections(
            image_annotations=image_annotations,
            resolution_wh=(image_width, image_height),
            with_masks=with_masks,
            use_iscrowd=use_iscrowd,
        )

        annotation = map_detections_class_id(
            source_to_target_mapping=class_index_mapping,
            detections=annotation,
        )

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Deduplicate the images array on file_name (keep one entry and remap its annotations' image_id).
  2. If two different images share a basename, move them into subdirectories and use distinct relative paths in file_name.
  3. Use check on resolved paths: {Path(imgs_dir, e['file_name']).resolve() for e in data['images']} length must equal len(data['images']).

Example fix

// before
"images": [{"id": 1, "file_name": "a.jpg", ...}, {"id": 2, "file_name": "a.jpg", ...}]

// after
"images": [{"id": 1, "file_name": "a.jpg", ...}]  # annotations for id 2 remapped to id 1 or second image renamed
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

def assert_unique_coco_images(annotations_path: str, images_dir: str) -> None:
    """Fail fast if two images[] entries resolve to the same path."""
    data = json.loads(Path(annotations_path).read_text())
    seen: dict[Path, int] = {}
    for img in data["images"]:
        p = Path(images_dir, img["file_name"]).resolve()
        if p in seen:
            raise ValueError(f"Duplicate file_name {img['file_name']!r} (also id {seen[p]})")
        seen[p] = img["id"]

Type guard

def coco_images_are_unique(entries: list[dict], images_dir: str) -> bool:
    """True when all resolved image paths are distinct."""
    paths = [str(Path(images_dir, e["file_name"]).resolve()) for e in entries]
    return len(set(paths)) == len(paths)

Try / catch

try:
    sv.DetectionDataset.from_coco(images_directory_path=d, annotations_path=a)
except ValueError as exc:
    if "duplicate entries" in str(exc):
        # deduplicate on resolved path, remap annotations' image_id, then retry
        ...
    raise

Prevention

When it happens

Trigger: Two images[] entries with identical file_name, or aliasing names like "img.jpg" and "./img.jpg" / "sub/../img.jpg" that resolve to the same path (resolution collapses aliases by design). Distinct ids with the same file_name also trigger it.

Common situations: Merging COCO files from multiple sources without deduplicating images; case-insensitive filesystems where 'A.jpg' and 'a.jpg' collide after resolution; JSON edited by hand to add an image that already exists.

Related errors


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