roboflow/supervision · error · ValueError

All values in custom_values must be between 0 and 1.

Error message

All values in custom_values must be between 0 and 1.

What it means

ColorAnnotator (and related annotators using per-detection color scaling) accepts an optional `custom_values` array that replaces per-detection statistics (e.g. tracking time) as the color-mapping input. Those values must be normalized to [0, 1] so they can be mapped onto the color gradient. The error is raised by `_validate_custom_values` in src/supervision/annotators/core.py:2994 when any value falls outside [0, 1].

Source

Thrown at src/supervision/annotators/core.py:2994

                raise ValueError(
                    "The provided detections do not contain confidence values. "
                    "Please provide `custom_values` or ensure that the detections "
                    "contain confidence values (e.g. by using a different model)."
                )

        else:
            if not isinstance(custom_values, (np.ndarray, list)):
                raise TypeError(
                    "custom_values must be either a numpy array or a list of floats."
                )

            if len(custom_values) != len(detections):
                raise ValueError(
                    "The length of custom_values must match the number of detections."
                )

            if not all(0 <= value <= 1 for value in custom_values):
                raise ValueError("All values in custom_values must be between 0 and 1.")

    @staticmethod
    @deprecated(  # type: ignore[untyped-decorator]
        target=_validate_custom_values.__func__,  # type: ignore[attr-defined]
        deprecated_in="0.29.0",
        remove_in="0.32.0",
    )
    def validate_custom_values(
        custom_values: npt.NDArray[np.float64] | list[float] | None,
        detections: Detections,
    ) -> None:
        void(custom_values, detections)


class CropAnnotator(BaseAnnotator):
    """
    A class for drawing scaled up crops of detections on the scene.
    """

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Min-max normalize the values to [0, 1] before passing: `(vals - vmin) / (vmax - vmin)` with a guard for `vmax == vmin`
  2. Clip values into range if slight overshoot is acceptable: `np.clip(vals, 0.0, 1.0)`
  3. Replace NaN/inf with 0 before passing: `np.nan_to_num(vals, nan=0.0, posinf=1.0, neginf=0.0)`
  4. Leave `custom_values=None` to let the annotator derive values from `detections.data` automatically

Example fix

// before
annotator.annotate(scene=frame, detections=detections, custom_values=[120, 300, 45])

// after
import numpy as np
vals = np.array([120, 300, 45], dtype=np.float64)
vmin, vmax = vals.min(), vals.max()
norm = (vals - vmin) / (vmax - vmin) if vmax > vmin else np.zeros_like(vals)
annotator.annotate(scene=frame, detections=detections, custom_values=norm)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def normalize_custom_values(values, detections) -> np.ndarray | None:
    """Return custom_values normalized to [0, 1] and length-matched, or None."""
    if values is None:
        return None
    arr = np.nan_to_num(np.asarray(values, dtype=np.float64), nan=0.0, posinf=1.0, neginf=0.0)
    if arr.shape != (len(detections),):
        raise ValueError(f"expected {len(detections)} values, got {arr.shape}")
    vmin, vmax = arr.min(), arr.max()
    if vmax > vmin:
        arr = (arr - vmin) / (vmax - vmin)
    else:
        arr = np.zeros_like(arr)
    return np.clip(arr, 0.0, 1.0)

Prevention

When it happens

Trigger: Calling `ColorAnnotator.annotate(scene, detections, custom_values=[...])` (or the constructor) with raw, un-normalized values such as pixel counts, seconds, or class ids; or with values computed on a different scale than the annotator expects. Also raised if a list is passed containing NaN/inf, since NaN fails the `0 <= value <= 1` comparison.

Common situations: Passing raw detection ages, track durations, or confidence sums directly instead of min-max normalizing them first; reusing values normalized against a stale min/max after new data arrives; NaN produced by division-by-zero during normalization.

Related errors


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