{"record":{"id":"fc1fd88552c457d0","repo":"roboflow/supervision","slug":"unsupported-metric-target-for-iou-calculation","errorCode":null,"errorMessage":"Unsupported metric target for IoU calculation","messagePattern":"Unsupported metric target for IoU calculation","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"src/supervision/metrics/mean_average_recall.py","lineNumber":455,"sourceCode":"                    prediction_confidence = np.asarray(\n                        predictions.confidence, dtype=np.float32\n                    )\n                    if self._metric_target == MetricTarget.BOXES:\n                        # BOXES target never yields CompactMask; narrow for mypy.\n                        iou = box_iou_batch(\n                            cast(npt.NDArray[np.number], target_contents),\n                            cast(npt.NDArray[np.number], prediction_contents),\n                        )\n                    elif self._metric_target == MetricTarget.MASKS:\n                        iou = mask_iou_batch(target_contents, prediction_contents)\n                    elif self._metric_target == MetricTarget.ORIENTED_BOUNDING_BOXES:\n                        # OBB target never yields CompactMask; narrow for mypy.\n                        iou = oriented_box_iou_batch(\n                            cast(npt.NDArray[np.number], target_contents),\n                            cast(npt.NDArray[np.number], prediction_contents),\n                        )\n                    else:\n                        raise ValueError(\n                            \"Unsupported metric target for IoU calculation\"\n                        )\n\n                    matches, _ = _match_detection_batch_with_target_indices(\n                        prediction_class_ids,\n                        target_class_ids,\n                        iou,\n                        iou_thresholds,\n                    )\n                    ignored_matches = np.zeros_like(matches, dtype=bool)\n\n                    sorted_indices = np.argsort(-prediction_confidence)\n                    stats.append(\n                        (\n                            matches[sorted_indices],\n                            ignored_matches[sorted_indices],\n                            np.arange(len(prediction_confidence)),\n                            prediction_class_ids[sorted_indices],","sourceCodeStart":437,"sourceCodeEnd":473,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/metrics/mean_average_recall.py#L437-L473","documentation":"Inside MeanAverageRecall.compute(), after extracting per-detection content, the code dispatches IoU computation by metric target: box_iou_batch for BOXES, mask_iou_batch for MASKS, oriented_box_iou_batch for ORIENTED_BOUNDING_BOXES. This ValueError is the else-branch exhaustiveness guard: the configured _metric_target matched none of the three. Like errors 340/341 it signals a corrupted or non-enum metric_target rather than a user data problem.","triggerScenarios":"An invalid metric_target value reaching the constructor (raw int, string, or foreign enum) that still passed the earlier content extraction via an unexpected path; mutating _metric_target between update() and compute(); pickling a metric across supervision versions with enum changes; custom forks adding a new MetricTarget member without extending this dispatch.","commonSituations":"Same class of misuse as 340/341: config-driven metric_target strings not validated; version skew between environments; fork/new-enum contributions forgetting the IoU dispatch table.","solutions":["Construct with a valid MetricTarget enum member: BOXES, MASKS, or ORIENTED_BOUNDING_BOXES","Validate config-sourced values against MetricTarget before constructing the metric","Do not mutate private state; create a new metric per target","Fork maintainers: extend the if/elif dispatch when adding a MetricTarget member"],"exampleFix":"// before\nmar = MeanAverageRecall(metric_target=object())  # nonsense target\nmar.compute()\n\n// after\nfrom supervision.metrics import MetricTarget\nmar = MeanAverageRecall(metric_target=MetricTarget.BOXES)\nmar.compute()","handlingStrategy":"type-guard","validationCode":"from supervision.metrics.mean_average_recall import MetricTarget\nassert isinstance(metric_target, MetricTarget), 'use MetricTarget enum members only'","typeGuard":"from supervision.metrics.mean_average_recall import MetricTarget\n\ndef is_supported_iou_target(value) -> bool:\n    \"\"\"True for the three targets with an IoU implementation in MAR.\"\"\"\n    return value in (MetricTarget.BOXES, MetricTarget.MASKS,\n                     MetricTarget.ORIENTED_BOUNDING_BOXES)","tryCatchPattern":"try:\n    mar.compute()\nexcept ValueError as e:\n    if 'Unsupported metric target' in str(e):\n        raise RuntimeError('metric_target corrupted; recreate MeanAverageRecall') from e\n    raise","preventionTips":["Only use enum members for metric_target","Fork authors: extend the IoU dispatch when adding enum values","Recreate metric objects instead of mutating internals"],"tags":["metrics","mean-average-recall","enum","exhaustiveness-guard","internal-api"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}