roboflow/supervision · error · ValueError
2D boolean mask row count {mask.shape[0]} does not match obj
Error message
2D boolean mask row count {mask.shape[0]} does not match object count {n}. What it means
F1Score._detections_content() mirrors Precision's: it extracts boxes, masks, or oriented boxes from Detections by metric target and raises for any MetricTarget beyond BOXES, MASKS, and ORIENTED_BOUNDING_BOXES. With the current enum the branch is unreachable defensive code that fails fast on unsupported/injected targets.
Source
Thrown at src/supervision/key_points/core.py:865
Args:
mask: A boolean array of shape `(n, m)` where `n` is the number of
objects and `m` is the number of keypoints per object. Every row
must select the same number of keypoints so that the result can be
stored in a uniform `(n, k, ...)` array.
Returns:
A new `KeyPoints` instance containing only the keypoints selected by
the mask for each object.
Raises:
ValueError: If `mask.shape[0]` does not match the number of objects, if
`mask.shape[1]` does not match the number of keypoints, or if
different rows of the mask select different numbers of `True` values.
"""
n = len(self.xy)
if mask.shape[0] != n:
raise ValueError(
f"2D boolean mask row count {mask.shape[0]} does not match "
f"object count {n}."
)
if mask.shape[1] != self.xy.shape[1]:
raise ValueError(
f"2D boolean mask column count {mask.shape[1]} does not match "
f"keypoint count {self.xy.shape[1]}."
)
counts = np.sum(mask, axis=1)
if n > 0 and not np.all(counts == counts[0]):
raise ValueError(
"Cannot filter keypoints with a 2D boolean mask where rows have "
"different numbers of True values. "
"All objects must select the same number of keypoints. "
f"Got counts per object: {counts.tolist()}"
)
k = int(counts[0]) if n > 0 else 0
xy_selected = np.zeros((n, k, self.xy.shape[2]), dtype=self.xy.dtype)View on GitHub (pinned to 7f254d9784)
Solutions
- Use a consistent, single supervision version across the project
- Use only BOXES, MASKS, or ORIENTED_BOUNDING_BOXES for F1Score
- Remove custom metric_target injections
Example fix
# before f1 = sv.F1Score(metric_target=unsupported_target) # -> ValueError on compute # after f1 = sv.F1Score(metric_target=sv.MetricTarget.BOXES)
Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED = {sv.MetricTarget.BOXES, sv.MetricTarget.MASKS, sv.MetricTarget.ORIENTED_BOUNDING_BOXES}
assert target in SUPPORTED, 'F1Score does not support this metric target' Type guard
def is_supported_f1_target(target: sv.MetricTarget) -> bool:
return target in {sv.MetricTarget.BOXES, sv.MetricTarget.MASKS, sv.MetricTarget.ORIENTED_BOUNDING_BOXES} Prevention
- Choose the metric target from the data you actually have (boxes/masks/OBB), not aspirational capability
- Keep supervision pinned to a single version
When it happens
Trigger: Constructing sv.F1Score(metric_target=<unsupported or future MetricTarget member>) in a version-skewed environment or with a patched enum, then calling update()/compute() with non-empty Detections.
Common situations: Mixed supervision versions after partial upgrades; custom enum values passed as metric_target.
Related errors
- 2D boolean mask column count {mask.shape[1]} does not match
- from_inference() operates on a single result at a time.You c
- Cannot filter keypoints with a 2D boolean mask where rows ha
- Value must be a np.ndarray or a list
- All KeyPoints must have the same number of keypoints per ske
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/87b5dc160b592e8c.
Report an issue: GitHub.