roboflow/supervision · error · ValueError
The number of predictions ({len(predictions)}) and targets (
Error message
The number of predictions ({len(predictions)}) and targets ({len(targets)}) during the update must be the same. What it means
MeanAveragePrecision.update() mirrors the recall metric's contract: predictions and targets may each be a single Detections or a list of Detections, but after list-wrapping the counts must be equal because entries are paired per image. This ValueError fires when len(predictions) != len(targets) at update time, before any internal class-agnostic rewriting happens.
Source
Thrown at src/supervision/metrics/mean_average_precision.py:1442
targets: Detections | list[Detections],
) -> MeanAveragePrecision:
"""
Add new predictions and targets to the metric, but do not compute the result.
Args:
predictions: The predicted detections.
targets: The ground-truth detections.
Returns:
The updated metric instance.
"""
if not isinstance(predictions, list):
predictions = [predictions]
if not isinstance(targets, list):
targets = [targets]
if len(predictions) != len(targets):
raise ValueError(
f"The number of predictions ({len(predictions)}) and"
f" targets ({len(targets)}) during the update must be the same."
)
if self._class_agnostic:
predictions = deepcopy(predictions)
targets = deepcopy(targets)
for prediction in predictions:
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)
View on GitHub (pinned to 7f254d9784)
Solutions
- Pass equal-length lists: one sv.Detections per image on both sides, using sv.Detections.empty() for frames without detections
- Fix accumulation loops to append to both lists in lockstep
- Assert len equality immediately before update() to fail with pipeline context
- Use zip(images, preds, targets) style loops so divergence is structurally impossible
Example fix
# before
for img, det in zip(images, detections):
preds.append(det)
if det is not None:
targets.append(load_gt(img)) # conditional append -> drift
map_.update(preds, targets)
# after
for img, det in zip(images, detections):
preds.append(det if det is not None else sv.Detections.empty())
targets.append(load_gt(img))
map_.update(preds, targets) Defensive patterns
Strategy: validation
Validate before calling
preds = preds if isinstance(preds, list) else [preds]
tgts = tgts if isinstance(tgts, list) else [tgts]
assert len(preds) == len(tgts), f'{len(preds)} preds vs {len(tgts)} targets'
map_.update(preds, tgts) Type guard
from supervision.detection.core import Detections
from typing import Union, List
def is_matched_detection_inputs(
preds: Union[Detections, List[Detections]],
tgts: Union[Detections, List[Detections]],
) -> bool:
"""True when both sides normalize to equal-length lists."""
p = preds if isinstance(preds, list) else [preds]
t = tgts if isinstance(tgts, list) else [tgts]
return len(p) == len(t) Prevention
- Accumulate predictions and targets in lockstep per image
- Use sv.Detections.empty() for prediction-less frames
- Assert count equality before each update()
When it happens
Trigger: map.update([p1, p2, p3], [t1, t2]); passing a list on one side and a single Detections on the other when counts mismatch; loop bugs appending to only one accumulator; skipping empty prediction frames in one list but not the other.
Common situations: Video pipelines dropping frames on inference errors; batching inference results but flattening targets differently; index drift after filtering images (e.g. removing corrupt images from targets only); notebooks incrementally built lists across cells.
Related errors
- The number of predictions ({len(predictions)}) and targets (
- The number of predictions ({total_images_predictions}) and t
- MeanAverageRecall metric requires `class_id` on both predict
- MeanAverageRecall metric requires `confidence` on prediction
- Invalid metric target: {self._metric_target}
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/3c1d926edda3b841.
Report an issue: GitHub.