roboflow/supervision · error · ValueError
`is_crowd` length ({len(is_crowd)}) must match `boxes_true`
Error message
`is_crowd` length ({len(is_crowd)}) must match `boxes_true` length ({len(boxes_true)}). What it means
Raised by sv.box_iou_batch_with_jaccard when the is_crowd flag array length does not equal the number of ground-truth boxes. is_crowd switches each ground-truth box between IoU and Jaccard-style overlap; supervision requires a one-to-one flag per ground-truth box, so a length mismatch is a caller error.
Source
Thrown at src/supervision/detection/utils/iou_and_nms.py:356
... ]
>>> boxes_detection = [
... [12, 22, 28, 38],
... [16, 26, 36, 46]
... ]
>>> is_crowd = [False, False]
>>> ious = sv.box_iou_batch_with_jaccard(
... boxes_true=boxes_true,
... boxes_detection=boxes_detection,
... is_crowd=is_crowd
... )
>>> ious # doctest: +ELLIPSIS
array([[0.886..., 0.496...],
[0.4 ..., 0.862...]])
```
"""
if len(is_crowd) != len(boxes_true):
raise ValueError(
f"`is_crowd` length ({len(is_crowd)}) must match "
f"`boxes_true` length ({len(boxes_true)})."
)
if len(boxes_detection) == 0 or len(boxes_true) == 0:
return np.empty((len(boxes_detection), len(boxes_true)), dtype=np.float64)
# Smallest number to avoid division by zero.
eps = np.spacing(1)
gt = np.asarray(boxes_true, dtype=np.float64)
dt = np.asarray(boxes_detection, dtype=np.float64)
crowd = np.asarray(is_crowd, dtype=bool)
# Boxes are [x, y, w, h]. Build the far corners as `x2 = x + w` (rather than
# reusing `w`) so that the area/intersection arithmetic is bit-identical to
# the per-pair reference it replaces.
gt_x2, gt_y2 = gt[:, 0] + gt[:, 2], gt[:, 1] + gt[:, 3]
dt_x2, dt_y2 = dt[:, 0] + dt[:, 2], dt[:, 1] + dt[:, 3]
View on GitHub (pinned to 7f254d9784)
Solutions
- Derive flags from the same filtering pass as boxes_true: is_crowd = np.array([a.get('iscrowd', 0) for a in gt_annos])
- Filter both together: mask = ...; boxes_true = boxes_true[mask]; is_crowd = is_crowd[mask]
- Default correctly when unsure: np.zeros(len(boxes_true), dtype=bool)
Example fix
# before keep = areas >= min_area ious = sv.box_iou_batch_with_jaccard(boxes_true[keep], boxes_detection, is_crowd=flags) # flags unfiltered # after keep = areas >= min_area ious = sv.box_iou_batch_with_jaccard(boxes_true[keep], boxes_detection, is_crowd=flags[keep])
Defensive patterns
Strategy: validation
Validate before calling
import numpy as np
def aligned_crowd_flags(boxes_true, is_crowd):
flags = np.asarray(is_crowd, dtype=bool).reshape(-1)
assert len(flags) == len(boxes_true), f"is_crowd {len(flags)} != boxes_true {len(boxes_true)}"
return flags Prevention
- Build is_crowd from the same annotation list you build boxes_true from
- Apply identical boolean filters to boxes and flags in evaluation code
- Default to np.zeros(len(boxes_true), dtype=bool) when crowd info is absent
When it happens
Trigger: sv.box_iou_batch_with_jaccard(boxes_true=gt, boxes_detection=dt, is_crowd=flags) with len(flags) != len(gt), e.g. flags computed from the detection array or a hard-coded np.zeros(5) reused after the GT set changed size.
Common situations: Reusing COCO-style is_crowd arrays after filtering ground truths (e.g. dropping ignore-region boxes) without filtering the flags in lockstep; building flags from the wrong list during evaluation-harness refactors; mAP/evaluation code where gt and flags come from different loaders.
Related errors
- masks_true and masks_detection must be 3D (N, H, W); got ndi
- box coordinates must be real-valued
- masks_true and masks_detection must share the same (H, W); g
- module {__name__} has no attribute {name}
- Edge indices must use the 1-based convention and be within t
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/eeccc37be752f9bd.
Report an issue: GitHub.