{"record":{"id":"bf8ccd7bc665dab2","repo":"roboflow/supervision","slug":"could-not-resolve-color-by-class-because-detection","errorCode":null,"errorMessage":"Could not resolve color by class because Detections do not have class_id. If using an annotator, try setting color_lookup to sv.ColorLookup.INDEX or sv.ColorLookup.TRACK.","messagePattern":"Could not resolve color by class because Detections do not have class_id\\. If using an annotator, try setting color_lookup to sv\\.ColorLookup\\.INDEX or sv\\.ColorLookup\\.TRACK\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/annotators/utils.py","lineNumber":60,"sourceCode":") -> int:\n    if detection_idx >= len(detections):\n        raise ValueError(\n            f\"Detection index {detection_idx} \"\n            f\"is out of bounds for detections of length {len(detections)}\"\n        )\n\n    if isinstance(color_lookup, np.ndarray):\n        if len(color_lookup) != len(detections):\n            raise ValueError(\n                f\"Length of color lookup {len(color_lookup)} \"\n                f\"does not match length of detections {len(detections)}\"\n            )\n        return int(color_lookup[detection_idx])\n    elif color_lookup == ColorLookup.INDEX:\n        return detection_idx\n    elif color_lookup == ColorLookup.CLASS:\n        if detections.class_id is None:\n            raise ValueError(\n                \"Could not resolve color by class because \"\n                \"Detections do not have class_id. If using an annotator, \"\n                \"try setting color_lookup to sv.ColorLookup.INDEX or \"\n                \"sv.ColorLookup.TRACK.\"\n            )\n        return int(detections.class_id[detection_idx])\n    elif color_lookup == ColorLookup.TRACK:\n        if detections.tracker_id is None:\n            raise ValueError(\n                \"Could not resolve color by track because \"\n                \"Detections do not have tracker_id. Did you call \"\n                \"tracker.update_with_detections(...) before annotating?\"\n            )\n        return int(detections.tracker_id[detection_idx])\n    raise ValueError(f\"Unsupported color lookup strategy: {color_lookup}\")\n\n\ndef resolve_text_background_xyxy(","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/annotators/utils.py#L42-L78","documentation":"Raised by `resolve_color_idx` when the color lookup strategy is the default `ColorLookup.CLASS` but `detections.class_id` is None. Mapping colors by class requires class ids; without them the palette cannot be indexed, so the annotator refuses to pick a color rather than guessing.","triggerScenarios":"Constructing `Detections(xyxy=..., confidence=...)` with no `class_id` and annotating with any default-configured annotator (BoxAnnotator, LabelAnnotator, etc. all default to `ColorLookup.CLASS`); using a connector or model output that omits class labels (e.g. class-agnostic detection); zero-row detections do not trigger this — only None class_id does.","commonSituations":"Quick prototypes with hand-built Detections fixtures that skip class_id; class-agnostic models (single-class heads that return boxes only); switching from a classifier-equipped model to a raw head while keeping the same annotation code.","solutions":["Pass `color_lookup=sv.ColorLookup.INDEX` to the annotator constructor so colors are assigned per detection index.","Populate `class_id` on the Detections (even a zeros array for single-class use).","If you track, `ColorLookup.TRACK` works once tracker ids exist — but class_id or INDEX is simpler."],"exampleFix":"# before\nannotator = sv.BoxAnnotator()  # default ColorLookup.CLASS\nannotator.annotate(scene, sv.Detections(xyxy=boxes))  # no class_id -> ValueError\n\n# after\nannotator = sv.BoxAnnotator(color_lookup=sv.ColorLookup.INDEX)\nannotator.annotate(scene, sv.Detections(xyxy=boxes))","handlingStrategy":"type-guard","validationCode":"lookup = (\n    sv.ColorLookup.CLASS if detections.class_id is not None\n    else sv.ColorLookup.INDEX\n)\nannotator = sv.BoxAnnotator(color_lookup=lookup)","typeGuard":"def color_lookup_for(detections) -> sv.ColorLookup:\n    if detections.tracker_id is not None:\n        return sv.ColorLookup.TRACK\n    if detections.class_id is not None:\n        return sv.ColorLookup.CLASS\n    return sv.ColorLookup.INDEX","tryCatchPattern":null,"preventionTips":["Default to ColorLookup.INDEX when building Detections without class_id.","Check detections.class_id is not None before using default annotator settings."],"tags":["annotators","color","configuration"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}