{"record":{"id":"c05792c423836271","repo":"roboflow/supervision","slug":"detections-class-id-must-be-an-integer-for-yolo-ex","errorCode":null,"errorMessage":"Detections class_id must be an integer for YOLO export, got {type(class_id)}.","messagePattern":"Detections class_id must be an integer for YOLO export, got (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/dataset/formats/yolo.py","lineNumber":389,"sourceCode":"            f\"`detections.data['{ORIENTED_BOX_COORDINATES}']` \"\n            \"(shape (N, 4, 2)) before exporting.\"\n        )\n\n    if is_obb and detections.mask is not None:\n        warnings.warn(\n            \"`detections.mask` is ignored when `is_obb=True`; \"\n            \"OBB annotations use corner coordinates from \"\n            f\"`detections.data['{ORIENTED_BOX_COORDINATES}']`.\",\n            UserWarning,\n            stacklevel=2,\n        )\n\n    annotation: list[str] = []\n    for xyxy, mask, _, class_id, _, data in detections:\n        if class_id is None:\n            raise ValueError(\"Class ID is required for YOLO annotations.\")\n        if not isinstance(class_id, (int, np.integer)):\n            raise ValueError(\n                f\"Detections class_id must be an integer for YOLO export, \"\n                f\"got {type(class_id)!r}.\"\n            )\n        class_id_int = int(class_id)\n\n        if is_obb:\n            corners = np.asarray(data[ORIENTED_BOX_COORDINATES], dtype=np.float32)\n            if corners.shape != (4, 2):\n                raise ValueError(\n                    f\"OBB data for each detection must have shape (4, 2), \"\n                    f\"got {corners.shape}. Ensure \"\n                    f\"`detections.data['{ORIENTED_BOX_COORDINATES}']` has \"\n                    \"shape (N, 4, 2) before exporting.\"\n                )\n            next_object = object_to_yolo(\n                xyxy=xyxy,\n                class_id=class_id_int,\n                image_shape=image_shape,","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/dataset/formats/yolo.py#L371-L407","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ndets.class_id = np.array([0.0, 1.0])  # float dtype\nlines = sv.detections_to_yolo_annotations(dets, image_shape=shape)\n# after\ndets.class_id = dets.class_id.astype(np.int64)\nlines = sv.detections_to_yolo_annotations(dets, image_shape=shape)","handlingStrategy":"validation","validationCode":"import numpy as np\n\ndef class_id_is_integer(detections) -> bool:\n    \"\"\"Check class_id dtype is integer (u/i kinds), not float/object.\"\"\"\n    return detections.class_id is not None and detections.class_id.dtype.kind in 'iu'","typeGuard":null,"tryCatchPattern":"try:\n    lines = sv.detections_to_yolo_annotations(dets, image_shape=shape)\nexcept ValueError as e:\n    if 'must be an integer' in str(e):\n        assert np.all(dets.class_id == dets.class_id.astype(np.int64))\n        dets.class_id = dets.class_id.astype(np.int64)\n        lines = sv.detections_to_yolo_annotations(dets, image_shape=shape)\n    else:\n        raise","preventionTips":["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."],"tags":["yolo","export","detections","dtype"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}