roboflow/supervision · error · ValueError
Class {class_name} not found in target classes. source_class
Error message
Class {class_name} not found in target classes. source_classes must be a subset of target_classes. What it means
Raised by build_class_index_mapping() when a class name in source_classes does not appear in target_classes. The function produces a source-index → target-index dict used to re-index annotations between datasets; a source class absent from the target list has no valid target index, so it fails with a subset requirement message.
Source
Thrown at src/supervision/dataset/utils.py:113
def merge_class_lists(class_lists: list[list[str]]) -> list[str]:
unique_classes = set()
for class_list in class_lists:
for class_name in class_list:
unique_classes.add(class_name)
return sorted(list(unique_classes))
def build_class_index_mapping(
source_classes: list[str], target_classes: list[str]
) -> dict[int, int]:
"""Returns the index map of source classes -> target classes."""
index_mapping = {}
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."
)View on GitHub (pinned to 7f254d9784)
Solutions
- Build the target class list with supervision.merge_class_lists() (used internally by merge) so it is the union of all datasets' classes.
- Normalize class name strings (strip/casefold) before comparing if names differ only by case or whitespace.
- Drop or rename the extra source classes that the target genuinely should not contain.
Example fix
// before mapping = build_class_index_mapping(src_ds.classes, tgt_ds.classes) # tgt missing classes // after from supervision.dataset.utils import merge_class_lists merged_classes = merge_class_lists([src_ds.classes, tgt_ds.classes]) mapping = build_class_index_mapping(src_ds.classes, merged_classes)
Defensive patterns
Strategy: validation
Validate before calling
missing = [c for c in source_classes if c not in target_classes]
if missing:
target_classes = merge_class_lists([target_classes, source_classes])
mapping = build_class_index_mapping(source_classes, target_classes) Type guard
def is_subset(source: list[str], target: list[str]) -> bool:
return set(source) <= set(target) Prevention
- Always build the target class list with merge_class_lists before mapping.
- Normalize class-name strings (strip, casefold) when combining datasets from different sources.
- Assert set(source) <= set(target) in dataset-merge tests.
When it happens
Trigger: Calling build_class_index_mapping(source_classes=['cat','dog','person'], target_classes=['cat','dog']) — 'person' is not in target. Common when merging two detection datasets whose class lists were collected independently.
Common situations: Using DetectionDataset.merge() or as_yolo/as_voc exports where classes differ across datasets; target classes derived from one dataset's annotations while the source has extra labels; case/whitespace differences in class names ('Cat' vs 'cat').
Related errors
- Image paths {duplicates} are not unique across datasets.
- All KeyPoints must have the same coordinate depth per skelet
- All or none of the '{name}' fields must be None
- Detections must have class_id attribute.
- Detections class_id must be a subset of source_to_target_map
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/bc06d8cd0a72bfcf.
Report an issue: GitHub.