roboflow/supervision · error · ValueError

CreateML annotation refers to image {image_name}, which reso

Error message

CreateML annotation refers to image {image_name}, which resolves to directory {resolved_image_path}. Expected a path to an image file.

What it means

Raised by _resolve_image_path in the CreateML loader when the resolved image path is an existing directory. The image field must resolve to a file; naming a directory (e.g. via a trailing slash or a folder name) is treated as malformed data.

Source

Thrown at src/supervision/dataset/formats/createml.py:49

    except (OSError, ValueError) as exc:
        raise ValueError(
            f"CreateML annotation refers to image {image_name!r}, which "
            f"produces an invalid path: {exc}"
        ) from exc
    if resolved_image_path == images_directory_resolved:
        raise ValueError(
            f"CreateML annotation refers to image {image_name!r}, which "
            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"CreateML 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"CreateML annotation refers to image {image_name!r}, which "
            f"resolves to directory {resolved_image_path}. Expected a path "
            "to an image file."
        )
    return str(resolved_image_path)


def createml_annotations_to_detections(
    image_annotations: list[CreateMLDict], class_to_index: dict[str, int]
) -> Detections:
    """Convert a single image's CreateML annotations into ``Detections``.

    CreateML stores each box as a pixel-space centre point plus width/height
    (``{"x", "y", "width", "height"}``); they are converted to ``xyxy`` corners.

    Args:
        image_annotations: List of annotation dicts for one image, each containing
            a ``"label"`` key and a ``"coordinates"`` dict with ``"x"``, ``"y"``,

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Point the image field at the actual file, with no trailing slash.
  2. Fix the generator script that assembled the path with an empty basename.
  3. Pre-validate: Path(images_dir, entry['image']).resolve().is_dir() should be False for every entry.

Example fix

// before
{"image": "train/", ...}

// after
{"image": "train/img_0001.jpg", ...}
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

def find_dir_valued_createml_images(annotations_path: str, images_dir: str) -> list[str]:
    """List 'image' values resolving to an existing directory."""
    entries = json.loads(Path(annotations_path).read_text())
    return [e["image"] for e in entries if Path(images_dir, e["image"]).resolve().is_dir()]

Type guard

def names_image_file_createml(name: str, images_dir: str) -> bool:
    """True when the resolved path exists and is a regular file."""
    return Path(images_dir, name).resolve().is_file()

Try / catch

try:
    sv.DetectionDataset.from_createml(images_directory_path=d, annotations_path=a)
except ValueError as exc:
    if "resolves to directory" in str(exc):
        raise ValueError(f"Fix directory-valued 'image' entries: {find_dir_valued_createml_images(a, d)}") from exc
    raise

Prevention

When it happens

Trigger: A CreateML entry with "image": "train/" or a name that happens to match a subdirectory inside images_directory_path.

Common situations: String concatenation bugs leaving a trailing '/'; empty filename joined after a folder prefix; directory/file name collisions in the dataset tree.

Related errors


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