roboflow/supervision · error · ValueError
CreateML annotation file must contain a JSON list at the roo
Error message
CreateML annotation file must contain a JSON list at the root, got {type(createml_data).__name__}. What it means
Raised by load_createml_annotations when the parsed JSON root is not a list. The CreateML annotation format is a JSON array of {image, annotations} objects; read_json_file may return a dict (object root) or other types, and this check fails fast with the actual type name.
Source
Thrown at src/supervision/dataset/formats/createml.py:174
- ``image_paths`` (``list[str]``): canonical resolved path for every
entry in the JSON, in file order.
- ``annotations`` (``dict[str, Detections]``): mapping from canonical
resolved image path to its ``Detections``.
Raises:
ValueError: If the JSON root is not a list.
ValueError: If an entry is missing the required ``"image"`` key.
ValueError: If an annotation is missing required coordinate or label keys.
ValueError: If two entries resolve to the same image path.
ValueError: If an annotation's ``image`` field resolves to the images
directory itself or to a path outside it (e.g. via ``..`` traversal
or an absolute path).
"""
createml_data = cast(
"list[CreateMLDict]", read_json_file(file_path=annotations_path)
)
if not isinstance(createml_data, list):
raise ValueError(
f"CreateML annotation file must contain a JSON list at the root, "
f"got {type(createml_data).__name__}."
)
try:
classes = sorted(
{
annotation["label"]
for entry in createml_data
for annotation in (entry.get("annotations") or [])
}
)
except (KeyError, TypeError) as exc:
raise ValueError(
f"Malformed CreateML annotation entry "
f"(missing or non-string 'label'): {exc}"
) from exc
class_to_index = {class_name: index for index, class_name in enumerate(classes)}View on GitHub (pinned to 7f254d9784)
Solutions
- Verify the file starts with '[' — CreateML format is a top-level array of entries.
- If your data is COCO format, use load_coco_annotations instead.
- If wrapped in an object, unwrap: data = json.load(f); entries = data['images'] and re-save as a list.
Example fix
// before: file content
{"images": [{"image": "a.jpg", "annotations": []}]}
// after
[{"image": "a.jpg", "annotations": []}] Defensive patterns
Strategy: type-guard
Validate before calling
import json
from pathlib import Path
def load_createml_list(annotations_path: str) -> list:
"""Parse CreateML JSON and assert a list root before calling the loader."""
data = json.loads(Path(annotations_path).read_text())
if not isinstance(data, list):
raise TypeError(f"Expected JSON list root, got {type(data).__name__}")
return data Type guard
def is_createml_format(data: object) -> bool:
"""True when data is a list of dicts with an 'image' key."""
return isinstance(data, list) and all(isinstance(e, dict) and "image" in e for e in data) Try / catch
try:
sv.DetectionDataset.from_createml(images_directory_path=d, annotations_path=a)
except ValueError as exc:
if "JSON list at the root" in str(exc):
raise TypeError(f"{a} is not a CreateML file; check the format (COCO?)") from exc
raise Prevention
- CreateML files are a top-level JSON array — verify the first non-whitespace byte is '['.
- Keep format-specific loaders paired with the right file extension in your pipeline.
- Write a tiny schema sniff test before bulk loading mixed datasets.
When it happens
Trigger: Calling load_createml_annotations / DetectionDataset.from_createml with a file whose root is a JSON object (e.g. {"images": [...]}, a COCO-style file) or any non-array JSON.
Common situations: Passing a COCO annotations JSON to the CreateML loader by mistake; tool exporting CreateML data wrapped in an object with metadata; passing the wrong file path (e.g. a config JSON).
Related errors
- CreateML annotation refers to image {image_name}, which reso
- CreateML annotation refers to image {image_name}, which reso
- CreateML annotation refers to image {image_name}, which reso
- CreateML annotation refers to image {image_name}, which prod
- Malformed CreateML annotation entry (missing or non-string '
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/2e50d7561ead3ade.
Report an issue: GitHub.