roboflow/supervision · error · ValueError
Detections class_id must be a subset of source_to_target_map
Error message
Detections class_id must be a subset of source_to_target_mapping keys.
What it means
Raised by map_detections_class_id() when detections contain class ids that have no entry in the source_to_target_mapping dict. The remap uses mapping.get(); unmapped ids would become None and corrupt the array, so supervision validates that detections.class_id ⊆ mapping.keys() first.
Source
Thrown at src/supervision/dataset/utils.py:129
for i, class_name in enumerate(source_classes):
if class_name not in target_classes:
raise ValueError(
f"Class {class_name} not found in target classes. "
"source_classes must be a subset of target_classes."
)
corresponding_index = target_classes.index(class_name)
index_mapping[i] = corresponding_index
return index_mapping
def map_detections_class_id(
source_to_target_mapping: dict[int, int], detections: Detections
) -> Detections:
if detections.class_id is None:
raise ValueError("Detections must have class_id attribute.")
if set(np.unique(detections.class_id)) - set(source_to_target_mapping.keys()):
raise ValueError(
"Detections class_id must be a subset of source_to_target_mapping keys."
)
detections_copy = copy.deepcopy(detections)
if len(detections) > 0:
detections_copy.class_id = np.vectorize(source_to_target_mapping.get)(
detections_copy.class_id
)
return detections_copy
def check_no_basename_collisions(
image_paths: list[str],
key: Callable[[str], str],
output_kind: str,
) -> None:View on GitHub (pinned to 7f254d9784)
Solutions
- Filter detections to known classes first: detections = detections[np.isin(detections.class_id, list(mapping.keys()))].
- Extend the mapping so it covers every class id present in the detections (rebuild with build_class_index_mapping over the full source class list).
- If extra classes should map to one bucket, add explicit entries for them.
Example fix
// before mapped = map_detections_class_id(mapping, dets) # dets contain unmapped ids // after known = np.isin(dets.class_id, list(mapping.keys())) mapped = map_detections_class_id(mapping, dets[known])
Defensive patterns
Strategy: validation
Validate before calling
valid_ids = set(source_to_target_mapping)
if not set(np.unique(detections.class_id)) <= valid_ids:
detections = detections[np.isin(detections.class_id, list(valid_ids))]
mapped = map_detections_class_id(source_to_target_mapping, detections) Type guard
def fully_mapped(mapping: dict[int, int], dets: sv.Detections) -> bool:
return set(np.unique(dets.class_id)) <= set(mapping) Prevention
- Build the mapping from the full source class list, not a subset.
- Filter detections to mapped classes before remapping.
- Unit-test that model output class ids are covered by the mapping.
When it happens
Trigger: Calling map_detections_class_id(mapping, detections) where the mapping was built from class lists that do not cover every class present in detections — e.g. detections from a model with 80 COCO classes mapped with a mapping built from a 10-class target subset.
Common situations: Merging datasets or exporting to YOLO/VOC where the target class list is a subset of the source; class lists built from annotation files that missed a rarely-occurring class; filter detections before remapping.
Related errors
- Detections must have class_id attribute.
- Detection annotation for image {image_path} contains non-int
- Detection annotation for image {image_path} contains class_i
- 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/da5fc728eb779405.
Report an issue: GitHub.