roboflow/supervision · error · ValueError

Detection annotation for image {image_path} contains non-int

Error message

Detection annotation for image {image_path} contains non-integer class_id values with dtype {class_ids.dtype}.

What it means

Raised by the DetectionDataset constructor during annotation validation when an annotation's class_id array has a non-integer dtype (e.g. float32). The constructor later indexes the class-name array with class_ids (np_classes[class_ids]) and fills CLASS_NAME_DATA_FIELD, which requires integer indices; float class ids would either fail indexing or hide data-quality bugs.

Source

Thrown at src/supervision/dataset/core.py:115

    ) -> None:
        self.classes = classes

        if set(images) != set(annotations):
            raise ValueError(
                "The keys of the images and annotations dictionaries must match."
            )
        self.annotations = {
            image_path: deepcopy(annotation)
            for image_path, annotation in annotations.items()
        }

        np_classes = np.array(self.classes)
        for image_path, annotation in self.annotations.items():
            class_ids = annotation.class_id
            if class_ids is None:
                continue
            if not np.issubdtype(class_ids.dtype, np.integer):
                raise ValueError(
                    f"Detection annotation for image {image_path!r} contains "
                    f"non-integer class_id values with dtype {class_ids.dtype}."
                )

            invalid_class_ids = class_ids[
                (class_ids < 0) | (class_ids >= len(self.classes))
            ]
            if len(invalid_class_ids) > 0:
                valid_range = (
                    "empty"
                    if len(self.classes) == 0
                    else f"[0, {len(self.classes) - 1}]"
                )
                raise ValueError(
                    f"Detection annotation for image {image_path!r} contains "
                    f"class_id {int(invalid_class_ids[0])}, outside the valid "
                    f"range {valid_range} for {len(self.classes)} classes."
                )

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Cast class_id to an integer dtype when building Detections: class_id=np.array(ids, dtype=np.int64).
  2. If parsing from JSON/COCO, map category ids through int(): np.array([int(a['category_id']) for a in anns], dtype=np.int64).
  3. Audit annotations before construction: assert all Detections.class_id is None or np.issubdtype(d.class_id.dtype, np.integer).

Example fix

// before
cls_ids = np.array([0.0, 2.0, 1.0])  # float dtype from JSON parsing
dets = sv.Detections(xyxy=boxes, class_id=cls_ids)

// after
cls_ids = np.array([0, 2, 1], dtype=np.int64)
dets = sv.Detections(xyxy=boxes, class_id=cls_ids)
Defensive patterns

Strategy: type-guard

Validate before calling

for path, dets in annotations.items():
    if dets.class_id is not None and not np.issubdtype(dets.class_id.dtype, np.integer):
        annotations[path] = replace(dets, class_id=dets.class_id.astype(np.int64))
ds = DetectionDataset(classes=classes, images=images, annotations=annotations)

Type guard

def integer_class_ids(dets: sv.Detections) -> bool:
    return dets.class_id is None or np.issubdtype(dets.class_id.dtype, np.integer)

Prevention

When it happens

Trigger: Constructing DetectionDataset with annotations whose class_id came from JSON/COCO parsing that produced floats (e.g. [[0.0], [2.0]]) and was cast to a float ndarray instead of int.

Common situations: Loading COCO annotations via the json module (all numbers are floats) and building Detections without astype(int); converting from CSVs that parse ids as floats; mixing dtypes when hand-assembling annotations.

Related errors


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