roboflow/supervision · warning · ValueError

Invalid metric target: {self._metric_target}

Error message

Invalid metric target: {self._metric_target}

What it means

MeanAveragePrecision raises this ValueError from _detections_content when its _metric_target matches none of BOXES, MASKS, ORIENTED_BOUNDING_BOXES after the per-target checks. It is the final exhaustiveness guard of the content extraction method; with any valid public MetricTarget enum member it is unreachable, so encountering it means an invalid value was injected into the private field (or a fork added an enum member without updating this method).

Source

Thrown at src/supervision/metrics/mean_average_precision.py:1485

            return None
        if self._metric_target == MetricTarget.MASKS:
            if detections.mask is None:
                raise ValueError(
                    "MeanAveragePrecision with `MetricTarget.MASKS` requires"
                    " masks on both predictions and targets."
                )
            return np.asarray(detections.mask).astype(bool)
        if self._metric_target == MetricTarget.ORIENTED_BOUNDING_BOXES:
            obb = detections.data.get(ORIENTED_BOX_COORDINATES)
            if obb is None:
                raise ValueError(
                    "MeanAveragePrecision with"
                    " `MetricTarget.ORIENTED_BOUNDING_BOXES` requires"
                    f" `{ORIENTED_BOX_COORDINATES}` in `data` on both"
                    " predictions and targets."
                )
            return np.asarray(obb, dtype=np.float32).reshape(-1, 4, 2)
        raise ValueError(f"Invalid metric target: {self._metric_target}")

    def _content_area(
        self, xywh: list[float], content: npt.NDArray[Any] | None, idx: int
    ) -> float:
        """Compute the default annotation area for the metric target: bbox area
        for boxes, pixel count for masks, polygon area for oriented boxes."""
        if content is None:
            return float(xywh[2] * xywh[3])
        if self._metric_target == MetricTarget.MASKS:
            return float(np.count_nonzero(content[idx]))
        x, y = content[idx, :, 0], content[idx, :, 1]
        # Shoelace formula
        return float(0.5 * abs(np.sum(x * np.roll(y, -1) - np.roll(x, -1) * y)))

    def _prepare_targets(
        self, targets: list[Detections]
    ) -> dict[str, list[_TypeCocoDict]]:
        """Transform targets into a dictionary that can be used by the COCO evaluator"""

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Pass a real MetricTarget enum member from supervision.metrics (or supervision.detection.core)
  2. Whitelist config values: MetricTarget(value) inside try/except ValueError before construction
  3. Pin a single supervision version across all environments
  4. Never mutate _metric_target; instantiate a fresh metric per target type

Example fix

// before
map_ = MeanAveragePrecision(metric_target=3)  # raw int, unknown
map_.compute()

// after
from supervision.metrics import MetricTarget
map_ = MeanAveragePrecision(metric_target=MetricTarget.MASKS)
map_.compute()
Defensive patterns

Strategy: type-guard

Validate before calling

from supervision.metrics.mean_average_precision import MeanAveragePrecision, MetricTarget
map_ = MeanAveragePrecision(metric_target=MetricTarget(target_from_config))

Type guard

from supervision.metrics.mean_average_precision import MetricTarget

def coerce_map_target(raw: object) -> MetricTarget:
    """Accept enum member or member name string; raise otherwise."""
    if isinstance(raw, MetricTarget):
        return raw
    if isinstance(raw, str):
        return MetricTarget[raw.upper()]
    raise TypeError(f'invalid metric_target: {raw!r}')

Try / catch

try:
    MeanAveragePrecision(metric_target=raw)
except ValueError:
    log.error('falling back to BOXES for invalid metric_target %r', raw)
    raise

Prevention

When it happens

Trigger: MeanAveragePrecision(metric_target=<non-enum value>) followed by update()/compute(); assigning to the private _metric_target attribute after construction; unpickling a metric saved by a different supervision version whose MetricTarget enum differs; supervision forks that add MetricTarget members without extending _detections_content.

Common situations: Passing metric_target as a string/int from config; version drift between dev and prod environments; copy-pasted kwargs from outdated snippets; test monkeypatching of internals.

Related errors


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