roboflow/supervision · error · ValueError
Length of color lookup {len(color_lookup)} does not match le
Error message
Length of color lookup {len(color_lookup)} does not match length of detections {len(detections)} What it means
Raised by `resolve_color_idx` in `supervision.annotators/utils.py` when a custom `color_lookup` is passed as a NumPy array whose length differs from the number of detections. The array maps each detection index to a palette/color index, so it must be aligned 1:1 with `detections`.
Source
Thrown at src/supervision/annotators/utils.py:51
@classmethod
def list(cls) -> list[str]:
return list(map(lambda c: c.value, cls))
def resolve_color_idx(
detections: Detections,
detection_idx: int,
color_lookup: ColorLookup | npt.NDArray[np.int_] = ColorLookup.CLASS,
) -> int:
if detection_idx >= len(detections):
raise ValueError(
f"Detection index {detection_idx} "
f"is out of bounds for detections of length {len(detections)}"
)
if isinstance(color_lookup, np.ndarray):
if len(color_lookup) != len(detections):
raise ValueError(
f"Length of color lookup {len(color_lookup)} "
f"does not match length of detections {len(detections)}"
)
return int(color_lookup[detection_idx])
elif color_lookup == ColorLookup.INDEX:
return detection_idx
elif color_lookup == ColorLookup.CLASS:
if detections.class_id is None:
raise ValueError(
"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."
)
return int(detections.class_id[detection_idx])
elif color_lookup == ColorLookup.TRACK:
if detections.tracker_id is None:
raise ValueError(View on GitHub (pinned to 7f254d9784)
Solutions
- Recompute the lookup after any filtering so `len(custom_color_lookup) == len(detections)`.
- Derive the array from the detections object itself at annotate time: `np.arange(len(detections))` or `detections.class_id`.
- If colors should follow classes, drop the custom array and use the default `ColorLookup.CLASS`.
Example fix
# before lookup = np.arange(len(detections)) detections = detections[detections.confidence > 0.5] # length changed annotator.annotate(scene, detections, custom_color_lookup=lookup) # ValueError # after lookup = np.arange(len(detections)) detections = detections[detections.confidence > 0.5] annotator.annotate(scene, detections, custom_color_lookup=np.arange(len(detections)))
Defensive patterns
Strategy: validation
Validate before calling
lookup = np.asarray(custom_color_lookup)
assert len(lookup) == len(detections), (
f"lookup {len(lookup)} != detections {len(detections)}"
)
annotator.annotate(scene, detections, custom_color_lookup=lookup) Try / catch
try:
annotator.annotate(scene, detections, custom_color_lookup=lookup)
except ValueError as e:
if "does not match length of detections" in str(e):
lookup = np.arange(len(detections)) # rebuild and retry once
annotator.annotate(scene, detections, custom_color_lookup=lookup)
else:
raise Prevention
- Derive custom_color_lookup from detections at annotate time, never cache it across filtering steps.
- Re-derive the lookup after every slice/filter of detections.
When it happens
Trigger: Calling an annotator's `annotate(scene, detections, custom_color_lookup=np.array([0, 1]))` when `len(detections) == 5`; reusing a `custom_color_lookup` array computed from last frame's detections while detections changed size after filtering (e.g. `detections = detections[detections.confidence > 0.5]`).
Common situations: Filtering detections (NMS, confidence threshold, zone filtering) between building the lookup array and calling annotate; caching a per-camera color mapping across frames with varying detection counts; passing class_id-derived lookups to a Detections whose length shrank after slicing.
Related errors
- Invalid hex color format: {hex_color}
- RGBA must be a 4-tuple with values between 0-255.
- '{CLASS_NAME_DATA_FIELD}' has {len(class_names)} entries but
- 'class_id' has {len(detections.class_id)} entries but detect
- Invalid hex digits in {hex_color}
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/897c7e9e0025a031.
Report an issue: GitHub.