{"record":{"id":"bbfdc5ebd770b4a2","repo":"roboflow/supervision","slug":"invalid-metric-target-self-metric-target-bbfdc5","errorCode":null,"errorMessage":"Invalid metric target: {self._metric_target}","messagePattern":"Invalid metric target: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"src/supervision/metrics/mean_average_precision.py","lineNumber":1485,"sourceCode":"            return None\n        if self._metric_target == MetricTarget.MASKS:\n            if detections.mask is None:\n                raise ValueError(\n                    \"MeanAveragePrecision with `MetricTarget.MASKS` requires\"\n                    \" masks on both predictions and targets.\"\n                )\n            return np.asarray(detections.mask).astype(bool)\n        if self._metric_target == MetricTarget.ORIENTED_BOUNDING_BOXES:\n            obb = detections.data.get(ORIENTED_BOX_COORDINATES)\n            if obb is None:\n                raise ValueError(\n                    \"MeanAveragePrecision with\"\n                    \" `MetricTarget.ORIENTED_BOUNDING_BOXES` requires\"\n                    f\" `{ORIENTED_BOX_COORDINATES}` in `data` on both\"\n                    \" predictions and targets.\"\n                )\n            return np.asarray(obb, dtype=np.float32).reshape(-1, 4, 2)\n        raise ValueError(f\"Invalid metric target: {self._metric_target}\")\n\n    def _content_area(\n        self, xywh: list[float], content: npt.NDArray[Any] | None, idx: int\n    ) -> float:\n        \"\"\"Compute the default annotation area for the metric target: bbox area\n        for boxes, pixel count for masks, polygon area for oriented boxes.\"\"\"\n        if content is None:\n            return float(xywh[2] * xywh[3])\n        if self._metric_target == MetricTarget.MASKS:\n            return float(np.count_nonzero(content[idx]))\n        x, y = content[idx, :, 0], content[idx, :, 1]\n        # Shoelace formula\n        return float(0.5 * abs(np.sum(x * np.roll(y, -1) - np.roll(x, -1) * y)))\n\n    def _prepare_targets(\n        self, targets: list[Detections]\n    ) -> dict[str, list[_TypeCocoDict]]:\n        \"\"\"Transform targets into a dictionary that can be used by the COCO evaluator\"\"\"","sourceCodeStart":1467,"sourceCodeEnd":1503,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/metrics/mean_average_precision.py#L1467-L1503","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a real MetricTarget enum member from supervision.metrics (or supervision.detection.core)","Whitelist config values: MetricTarget(value) inside try/except ValueError before construction","Pin a single supervision version across all environments","Never mutate _metric_target; instantiate a fresh metric per target type"],"exampleFix":"// before\nmap_ = MeanAveragePrecision(metric_target=3)  # raw int, unknown\nmap_.compute()\n\n// after\nfrom supervision.metrics import MetricTarget\nmap_ = MeanAveragePrecision(metric_target=MetricTarget.MASKS)\nmap_.compute()","handlingStrategy":"type-guard","validationCode":"from supervision.metrics.mean_average_precision import MeanAveragePrecision, MetricTarget\nmap_ = MeanAveragePrecision(metric_target=MetricTarget(target_from_config))","typeGuard":"from supervision.metrics.mean_average_precision import MetricTarget\n\ndef coerce_map_target(raw: object) -> MetricTarget:\n    \"\"\"Accept enum member or member name string; raise otherwise.\"\"\"\n    if isinstance(raw, MetricTarget):\n        return raw\n    if isinstance(raw, str):\n        return MetricTarget[raw.upper()]\n    raise TypeError(f'invalid metric_target: {raw!r}')","tryCatchPattern":"try:\n    MeanAveragePrecision(metric_target=raw)\nexcept ValueError:\n    log.error('falling back to BOXES for invalid metric_target %r', raw)\n    raise","preventionTips":["Route all metric_target values through an enum coercion helper","Validate at config load, not at compute time","Keep supervision versions consistent"],"tags":["metrics","mean-average-precision","enum","validation","exhaustiveness-guard"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}