roboflow/supervision · error · ValueError
Detections class_id must be an integer for YOLO export, got
Error message
Detections class_id must be an integer for YOLO export, got {type(class_id)}. What it means
Raised when a detection's class_id is present but is not a Python or NumPy integer (isinstance check against (int, np.integer) fails). YOLO export formats the class index as an integer token, so float class ids (e.g. 0.0) or other types are rejected to prevent silently writing wrong labels. Note bool is technically int in Python but typically arrives as np types here.
Source
Thrown at src/supervision/dataset/formats/yolo.py:389
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,
class_id=class_id_int,
image_shape=image_shape,View on GitHub (pinned to 7f254d9784)
Solutions
- Cast the array before export: detections.class_id = detections.class_id.astype(np.int64) (after ensuring values are whole numbers).
- Fix the connector/code that produced the non-integer class_id to emit int dtype from the start.
- If class ids come from a pandas column, use .astype('int64') on read.
Example fix
# before dets.class_id = np.array([0.0, 1.0]) # float dtype lines = sv.detections_to_yolo_annotations(dets, image_shape=shape) # after dets.class_id = dets.class_id.astype(np.int64) lines = sv.detections_to_yolo_annotations(dets, image_shape=shape)
Defensive patterns
Strategy: validation
Validate before calling
import numpy as np
def class_id_is_integer(detections) -> bool:
"""Check class_id dtype is integer (u/i kinds), not float/object."""
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 'must be an integer' in str(e):
assert np.all(dets.class_id == dets.class_id.astype(np.int64))
dets.class_id = dets.class_id.astype(np.int64)
lines = sv.detections_to_yolo_annotations(dets, image_shape=shape)
else:
raise Prevention
- Cast class ids to int at model-output conversion time, not at export time.
- Beware pandas float columns and JSON round-trips turning ids into floats.
- Assert dtype in unit tests for custom connectors.
When it happens
Trigger: sv.detections_to_yolo_annotations(...) where detections.class_id is a float array (dtype float32/float64), a list of strings, or object dtype — e.g. class ids computed from float scores or loaded from CSV without casting.
Common situations: class_id arrays created via argmax then stored in a float container; reading ids from pandas DataFrames (int64 usually fine, but float columns are not); JSON round-trips that turn ids into floats; custom connectors that forget dtype.
Related errors
- `is_obb=True` requires `'{ORIENTED_BOX_COORDINATES}'` in `de
- Class ID is required for YOLO annotations.
- OBB data for each detection must have shape (4, 2), got {cor
- class_id is required for LabelMe export, but the provided De
- Detections must have class_id attribute.
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/c05792c423836271.
Report an issue: GitHub.