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

  1. Recompute the lookup after any filtering so `len(custom_color_lookup) == len(detections)`.
  2. Derive the array from the detections object itself at annotate time: `np.arange(len(detections))` or `detections.class_id`.
  3. 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

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


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/897c7e9e0025a031. Report an issue: GitHub.