roboflow/supervision · error · ValueError
MeanAveragePrecision with `MetricTarget.MASKS` requires mask
Error message
MeanAveragePrecision with `MetricTarget.MASKS` requires masks on both predictions and targets.
What it means
When MeanAveragePrecision is configured with metric_target=MetricTarget.MASKS, _detections_content must return each detection's boolean mask to compute mask IoU. This ValueError fires when detections.mask is None for a non-empty Detections object (the method returns None early for empty detections, so only populated detections are checked). It is raised for whichever side — predictions or targets — lacks masks.
Source
Thrown at src/supervision/metrics/mean_average_precision.py:1470
if prediction.class_id is not None:
prediction.class_id[:] = -1
for target in targets:
if target.class_id is not None:
target.class_id[:] = -1
self._predictions_list.extend(predictions)
self._targets_list.extend(targets)
return self
def _detections_content(self, detections: Detections) -> npt.NDArray[Any] | None:
"""Return per-detection masks or oriented boxes for the metric target,
or `None` for the box target and for empty detections."""
if self._metric_target == MetricTarget.BOXES or len(detections) == 0:
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: intView on GitHub (pinned to 7f254d9784)
Solutions
- Populate .mask on both predictions and targets: sv.Detections(..., mask=bool_array_of_shape_NHW)
- Use a segmentation model and its connector so masks flow through automatically
- If you only have boxes, evaluate with the default MetricTarget.BOXES
- Pre-check before update: require (det.mask is not None) or det.is_empty() for both sides
Example fix
# before
map_ = sv.MeanAveragePrecision(metric_target=sv.MetricTarget.MASKS)
preds = sv.Detections(xyxy=boxes, class_id=ids, confidence=confs)
map_.update(preds, targets) # no masks -> ValueError
# after
preds = sv.Detections(xyxy=boxes, class_id=ids, confidence=confs,
mask=pred_masks) # (N, H, W) bool
targets = sv.Detections(xyxy=gt_boxes, class_id=gt_ids, mask=gt_masks)
map_.update(preds, targets) Defensive patterns
Strategy: validation
Validate before calling
def masks_ok(dets) -> bool:
"""MASKS-target precondition: empty or carries .mask."""
return len(dets) == 0 or dets.mask is not None
assert masks_ok(preds) and masks_ok(targets) Type guard
from supervision.detection.core import Detections
def has_mask_data(dets: Detections) -> bool:
"""True when Detections is empty or has a populated mask field."""
return dets.mask is not None or dets.is_empty() Prevention
- Match metric_target to the model task: MASKS only with segmentation models
- Populate mask= on both predictions and targets from the same preprocessor
- Add a pipeline precondition check before update()
When it happens
Trigger: MeanAveragePrecision(metric_target=MetricTarget.MASKS).update() with box-only Detections (no mask= kwarg); segmentation model output passed through a detection-only connector that drops masks; masks present on predictions but ground-truth Detections built from bounding-box annotations only; class-agnostic deep-copies in update() still carry no masks.
Common situations: Switching metric_target from BOXES to MASKS without switching models/annotation loaders to segmentation; evaluating a detector checkpoint with the segmentation metric; GT annotation pipeline (COCO boxes, Pascal VOC) that never produced masks; one-sided mask availability (predictions segmented, GT boxed).
Related errors
- MeanAverageRecall with `MetricTarget.MASKS` requires detecti
- All KeyPoints must have the same number of keypoints per ske
- Invalid metric target: {self._metric_target}
- results must be a list
- Results do not correspond to current coco set
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/6e76772308bc4639.
Report an issue: GitHub.