roboflow/supervision · error · ValueError
Detection annotation for image {image_path} contains class_i
Error message
Detection annotation for image {image_path} contains class_id {int(invalid_class_ids[0])}, outside the valid range {valid_range} for {len(self.classes)} classes. What it means
Raised by the DetectionDataset constructor when an annotation contains a class_id outside [0, len(classes)-1]. Right after this check the constructor does np_classes[class_ids] to attach class-name metadata; an out-of-range id would raise a cryptic IndexError instead, so it validates first and reports the offending image, id, and valid range. An empty classes list yields 'empty' as the valid range.
Source
Thrown at src/supervision/dataset/core.py:129
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."
)
annotation.data[CLASS_NAME_DATA_FIELD] = np_classes[class_ids]
# Eliminate duplicates while preserving order
self.image_paths = list(dict.fromkeys(images))
self._images_in_memory: dict[str, npt.NDArray[np.uint8]] = {}
if isinstance(images, dict):
self._images_in_memory = images
warn_deprecated(
"Passing a `Dict[str, np.ndarray]` into `DetectionDataset` is "
"deprecated in `0.30.0` and will be removed in `0.33.0`. Use "
"a list of paths `List[str]` instead."
)View on GitHub (pinned to 7f254d9784)
Solutions
- Remap raw category ids to contiguous 0-based indices using the classes list (the same logic as build_class_index_mapping) before constructing Detections.
- Extend the classes list so it covers every id present: classes must have at least max(class_id)+1 entries.
- Drop or fix annotations with ids beyond your class list.
Example fix
// before
classes = ['cat', 'dog']
dets = sv.Detections(xyxy=boxes, class_id=np.array([1, 3, 7])) # 3, 7 out of range
ds = DetectionDataset(classes=classes, images=paths, annotations=anns)
// after
# remap sparse COCO-style ids to contiguous indices
cat_to_idx = {c: i for i, c in enumerate(['cat', 'dog', 'horse', ...])}
dets = sv.Detections(xyxy=boxes, class_id=np.array([cat_to_idx[c] for c in ['dog', 'horse', ...]]))
ds = DetectionDataset(classes=list(cat_to_idx), images=paths, annotations=anns) Defensive patterns
Strategy: validation
Validate before calling
for path, dets in annotations.items():
if dets.class_id is not None and len(dets.class_id) and (dets.class_id.max() >= len(classes) or dets.class_id.min() < 0):
raise ValueError(f"{path}: class_id outside [0, {len(classes) - 1}]")
ds = DetectionDataset(classes=classes, images=images, annotations=annotations) Type guard
def class_ids_in_range(dets: sv.Detections, num_classes: int) -> bool:
if dets.class_id is None:
return True
return bool(np.all((dets.class_id >= 0) & (dets.class_id < num_classes))) Prevention
- Remap sparse COCO category ids to contiguous 0-based indices before building Detections.
- Ensure the classes list covers max(class_id) + 1 entries.
- Never construct a dataset with classes=[] while annotations carry class ids.
When it happens
Trigger: Constructing DetectionDataset(classes=['cat','dog'], ...) with an annotation containing class_id=3 (valid range is [0,1]); or passing annotations with ids offset by 1; or building the dataset with an empty classes list while annotations carry ids.
Common situations: COCO datasets where category_id is not contiguous (e.g. ids 1,3,7 used directly without remapping to indices); merging datasets with different class orderings; forgetting that classes=[] invalidates every id; off-by-one from 1-based id schemes.
Related errors
- Detection annotation for image {image_path} contains non-int
- Detections must have class_id attribute.
- Detections class_id must be a subset of source_to_target_map
- KeyPoints class_id must be given for NMS to be executed. If
- Class {class_name} not found in target classes. source_class
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/c0906daee36b3a4d.
Report an issue: GitHub.