roboflow/supervision · error · ValueError

mask must contain {n} masks, but got {len(mask)}

Error message

mask must contain {n} masks, but got {len(mask)}

What it means

Raised by supervision.validators._validate_mask when the mask is a CompactMask whose entry count differs from n, the number of rows in xyxy. Each detection needs exactly one mask; with CompactMask the count check is a simple len() comparison before shape checks apply to the decompressed form.

Source

Thrown at src/supervision/validators/__init__.py:45

@deprecated(  # type: ignore[untyped-decorator]
    target=_validate_xyxy,
    deprecated_in="0.29.0",
    remove_in="0.32.0",
)
def validate_xyxy(xyxy: Any) -> None:
    void(xyxy)


def _validate_mask(mask: Any, n: int) -> None:
    if mask is None:
        return

    # Fast path: CompactMask only needs a length check.

    if isinstance(mask, CompactMask):
        if len(mask) != n:
            raise ValueError(f"mask must contain {n} masks, but got {len(mask)}")
        return

    expected_shape = f"({n}, H, W)"
    actual_shape = str(getattr(mask, "shape", None))
    actual_dtype = getattr(mask, "dtype", None)

    is_valid_shape = (
        isinstance(mask, np.ndarray) and len(mask.shape) == 3 and mask.shape[0] == n
    )
    if not is_valid_shape:
        raise ValueError(
            "mask must be a 3D np.ndarray with shape "
            + f"{expected_shape}, but got shape {actual_shape}"
        )
    if not np.issubdtype(actual_dtype, bool):
        warn_deprecated(
            f"A `Detections` object was created with a mask of type {actual_dtype}."
            " Masks of type other than `bool` are deprecated and may produce unexpected"

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Apply the same filter mask to both: det = det[keep_idx] via Detections.__getitem__, which keeps xyxy and mask aligned.
  2. Rebuild the CompactMask from the filtered mask array after selection.
  3. Assert len(mask) == len(xyxy) before constructing Detections.

Example fix

# before
dets = Detections(xyxy=boxes, mask=compact_mask)  # 10 boxes, 9 masks

# after
keep = confidence > 0.5
dets = Detections(xyxy=boxes[keep], mask=CompactMask.from_mask(masks_arr[keep]))
Defensive patterns

Strategy: validation

Validate before calling

assert len(compact_mask) == len(xyxy), (
    f"mask count {len(compact_mask)} != box count {len(xyxy)}"
)
dets = Detections(xyxy=xyxy, mask=compact_mask)

Type guard

def mask_matches_boxes(mask: CompactMask, xyxy: np.ndarray) -> bool:
    return len(mask) == len(xyxy)

Prevention

When it happens

Trigger: Constructing Detections(xyxy=boxes, mask=CompactMask(...)) where len(mask) != len(boxes); e.g. 10 boxes with 9 encoded masks after filtering boxes but not masks.

Common situations: Applying confidence/class filters to xyxy but forgetting the mask; combining boxes and masks produced at different pipeline stages (NMS applied to one, not the other); serializing/deserializing CompactMask and losing an entry.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/9fd6ae5933af03ed. Report an issue: GitHub.