roboflow/supervision · error · ValueError

Class ID is required for YOLO annotations.

Error message

Class ID is required for YOLO annotations.

What it means

Raised by detections_to_yolo_annotations when iterating detections and a detection's class_id is None. YOLO annotation lines start with a class index, so a class-less Detections (e.g. from a tracker that dropped class_id or a manually built empty-class Detections) cannot be serialized.

Source

Thrown at src/supervision/dataset/formats/yolo.py:387

            "`detections.data` with shape (N, 4, 2). Load OBB datasets via "
            "`DetectionDataset.from_yolo(..., is_obb=True)` or set "
            f"`detections.data['{ORIENTED_BOX_COORDINATES}']` "
            "(shape (N, 4, 2)) before exporting."
        )

    if is_obb and detections.mask is not None:
        warnings.warn(
            "`detections.mask` is ignored when `is_obb=True`; "
            "OBB annotations use corner coordinates from "
            f"`detections.data['{ORIENTED_BOX_COORDINATES}']`.",
            UserWarning,
            stacklevel=2,
        )

    annotation: list[str] = []
    for xyxy, mask, _, class_id, _, data in detections:
        if class_id is None:
            raise ValueError("Class ID is required for YOLO annotations.")
        if not isinstance(class_id, (int, np.integer)):
            raise ValueError(
                f"Detections class_id must be an integer for YOLO export, "
                f"got {type(class_id)!r}."
            )
        class_id_int = int(class_id)

        if is_obb:
            corners = np.asarray(data[ORIENTED_BOX_COORDINATES], dtype=np.float32)
            if corners.shape != (4, 2):
                raise ValueError(
                    f"OBB data for each detection must have shape (4, 2), "
                    f"got {corners.shape}. Ensure "
                    f"`detections.data['{ORIENTED_BOX_COORDINATES}']` has "
                    "shape (N, 4, 2) before exporting."
                )
            next_object = object_to_yolo(
                xyxy=xyxy,

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Attach class ids when constructing: Detections(xyxy=..., class_id=np.array([0, 1], dtype=int)).
  2. If classes are genuinely unknown, assign a placeholder class (e.g. zeros) before export.
  3. Check any intermediate step (tracker, smoother, filter) that returns class_id=None and re-attach classes by tracker_id mapping.

Example fix

# before
dets = sv.Detections(xyxy=xyxy)  # no class_id
lines = sv.detections_to_yolo_annotations(dets, image_shape=shape)
# after
dets = sv.Detections(xyxy=xyxy, class_id=np.zeros(len(xyxy), dtype=int))
lines = sv.detections_to_yolo_annotations(dets, image_shape=shape)
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np

def ready_for_yolo_export(detections) -> bool:
    """YOLO export needs a non-None class_id array."""
    return detections.class_id is not None

Type guard

def has_class_id(detections) -> bool:
    """True when every detection carries an integer class id."""
    return detections.class_id is not None and detections.class_id.dtype.kind in 'iu'

Try / catch

try:
    lines = sv.detections_to_yolo_annotations(dets, image_shape=shape)
except ValueError as e:
    if 'Class ID is required' in str(e):
        dets.class_id = np.zeros(len(dets), dtype=np.int64)  # placeholder class
        lines = sv.detections_to_yolo_annotations(dets, image_shape=shape)
    else:
        raise

Prevention

When it happens

Trigger: Calling sv.detections_to_yolo_annotations(...) (or as_yolo_annotations on a dataset) where detections.class_id is None — commonly Detections created with only xyxy, or a class_id array that was deliberately cleared.

Common situations: Building Detections from raw model output without wiring class ids; using tracker output where class_id was not propagated; slicing/filtering detections and losing class_id; testing code with minimal Detections(xyxy=...) constructions.

Related errors


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