roboflow/supervision · error · ValueError
CreateML annotation file contains duplicate entries for imag
Error message
CreateML annotation file contains duplicate entries for image {image_name}. Each image must appear at most once. What it means
Raised by load_createml_annotations when two entries resolve to the same canonical image path (dict lookup on the resolved path). Each image may appear at most once; a duplicate would silently overwrite the earlier entry's Detections.
Source
Thrown at src/supervision/dataset/formats/createml.py:211
image_paths: list[str] = []
annotations: dict[str, Detections] = {}
for entry in tqdm(
createml_data,
desc="Loading CreateML annotations",
disable=not show_progress,
):
image_name = entry.get("image")
if image_name is None:
raise ValueError(
f"CreateML annotation entry is missing the required 'image' key: "
f"{entry!r}"
)
image_path = _resolve_image_path(
images_directory_path=images_directory_path, image_name=image_name
)
if image_path in annotations:
raise ValueError(
f"CreateML annotation file contains duplicate entries for image "
f"{image_name!r}. Each image must appear at most once."
)
annotations[image_path] = createml_annotations_to_detections(
image_annotations=entry.get("annotations") or [],
class_to_index=class_to_index,
)
image_paths.append(image_path)
return classes, image_paths, annotations
def detections_to_createml_annotations(
detections: Detections, classes: list[str]
) -> list[CreateMLDict]:
"""Convert ``Detections`` into a list of CreateML annotation dicts.
Each bounding box is stored as a pixel-space centre point plus width andView on GitHub (pinned to 7f254d9784)
Solutions
- Deduplicate entries on the resolved image path, merging their annotations arrays if both are valid.
- Check for duplicates before loading: paths = [Path(imgs_dir, e['image']).resolve() for e in data]; assert len(set(paths)) == len(paths).
- If two distinct images share a basename, put them in subfolders and use distinct relative paths.
Example fix
// before
[{"image": "a.jpg", "annotations": [...]}, {"image": "./a.jpg", "annotations": [...]}]
// after
[{"image": "a.jpg", "annotations": [...merged...]}] Defensive patterns
Strategy: validation
Validate before calling
import json
from pathlib import Path
def assert_unique_createml_images(annotations_path: str, images_dir: str) -> None:
"""Fail fast if two entries resolve to the same image path."""
entries = json.loads(Path(annotations_path).read_text())
seen: set[str] = set()
for e in entries:
p = str(Path(images_dir, e["image"]).resolve())
if p in seen:
raise ValueError(f"Duplicate image {e['image']!r}")
seen.add(p) Type guard
def createml_images_are_unique(entries: list[dict], images_dir: str) -> bool:
"""True when all resolved image paths are distinct."""
paths = [str(Path(images_dir, e["image"]).resolve()) for e in entries]
return len(set(paths)) == len(paths) Try / catch
try:
sv.DetectionDataset.from_createml(images_directory_path=d, annotations_path=a)
except ValueError as exc:
if "duplicate entries" in str(exc):
# merge annotations arrays for duplicated images, then retry
...
raise Prevention
- Deduplicate on resolved paths whenever you concatenate CreateML files.
- Remember './a.jpg' and 'a.jpg' are the same image to the loader.
- Automate a uniqueness check in CI for generated annotation files.
When it happens
Trigger: Two entries with the same "image" value, or aliasing values ("a.jpg" vs "./a.jpg") that collapse after resolution — the resolver deliberately canonicalizes so aliases do not sneak past this check.
Common situations: Concatenating per-batch CreateML files without deduplication; copy-pasted entries; case-insensitive filesystems where differently-cased names collide.
Related errors
- COCO annotation file contains duplicate entries for image {i
- CreateML annotation refers to image {image_name}, which reso
- CreateML annotation refers to image {image_name}, which reso
- Malformed CreateML annotation entry (missing or non-string '
- COCO annotation refers to image {image_name}, which resolves
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/448365560ca1a281.
Report an issue: GitHub.