{"record":{"id":"ff25bece31bc5526","repo":"roboflow/supervision","slug":"could-not-resolve-color-by-track-because-detection","errorCode":null,"errorMessage":"Could not resolve color by track because Detections do not have tracker_id. Did you call tracker.update_with_detections(...) before annotating?","messagePattern":"Could not resolve color by track because Detections do not have tracker_id\\. Did you call tracker\\.update_with_detections\\(\\.\\.\\.\\) before annotating\\?","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/annotators/utils.py","lineNumber":69,"sourceCode":"            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(\n    center_coordinates: tuple[int, int],\n    text_wh: tuple[int, int],\n    position: Position,\n) -> tuple[int, int, int, int]:\n    \"\"\"Compute the background box for text anchored at `position`.\"\"\"\n    center_x, center_y = center_coordinates\n    text_w, text_h = text_wh\n\n    if position == Position.TOP_LEFT:","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/annotators/utils.py#L51-L87","documentation":"Raised by `resolve_color_idx` when `color_lookup=ColorLookup.TRACK` is selected but `detections.tracker_id` is None. Track-based coloring needs per-detection tracker ids so each object keeps a stable color across frames.","triggerScenarios":"Constructing an annotator with `color_lookup=sv.ColorLookup.TRACK` and annotating detections that have not passed through `tracker.update_with_detections(...)`; annotating the first frame before the tracker call due to a loop-order bug; using a tracker's internal model results instead of the tracker's returned Detections.","commonSituations":"Reordering a video loop so annotation happens before tracking after a refactor; forgetting that only the Detections RETURNED by `update_with_detections` carry `tracker_id`; mixing tracked detections with freshly detected ones (e.g. concatenating) which can drop the field.","solutions":["Move the annotate call after `detections = tracker.update_with_detections(detections)`.","If tracking is not intended, switch to `ColorLookup.INDEX` or `ColorLookup.CLASS`.","Ensure every code path through the frame loop produces tracker-updated detections before annotating."],"exampleFix":"# before\nannotator = sv.BoxAnnotator(color_lookup=sv.ColorLookup.TRACK)\nscene = annotator.annotate(scene, detections)  # detections not tracked yet\ntracker.update_with_detections(detections)\n\n# after\nannotator = sv.BoxAnnotator(color_lookup=sv.ColorLookup.TRACK)\ndetections = tracker.update_with_detections(detections)\nscene = annotator.annotate(scene, detections)","handlingStrategy":"type-guard","validationCode":"if annotator.color_lookup == sv.ColorLookup.TRACK and detections.tracker_id is None:\n    detections = tracker.update_with_detections(detections)\nannotator.annotate(scene, detections)","typeGuard":"def is_tracked(detections) -> bool:\n    return detections.tracker_id is not None","tryCatchPattern":null,"preventionTips":["Order each frame loop: detect -> track -> annotate.","Use only the Detections returned by update_with_detections; other copies lack tracker_id."],"tags":["tracking","annotators","color"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}