{"record":{"id":"baf9bb7d4e639fa1","repo":"roboflow/supervision","slug":"2d-boolean-mask-column-count-mask-shape-1-does","errorCode":null,"errorMessage":"2D boolean mask column count {mask.shape[1]} does not match keypoint count {self.xy.shape[1]}.","messagePattern":"2D boolean mask column count (.+?) does not match keypoint count (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/key_points/core.py","lineNumber":870,"sourceCode":"                stored in a uniform `(n, k, ...)` array.\n\n        Returns:\n            A new `KeyPoints` instance containing only the keypoints selected by\n            the mask for each object.\n\n        Raises:\n            ValueError: If `mask.shape[0]` does not match the number of objects, if\n                `mask.shape[1]` does not match the number of keypoints, or if\n                different rows of the mask select different numbers of `True` values.\n        \"\"\"\n        n = len(self.xy)\n        if mask.shape[0] != n:\n            raise ValueError(\n                f\"2D boolean mask row count {mask.shape[0]} does not match \"\n                f\"object count {n}.\"\n            )\n        if mask.shape[1] != self.xy.shape[1]:\n            raise ValueError(\n                f\"2D boolean mask column count {mask.shape[1]} does not match \"\n                f\"keypoint count {self.xy.shape[1]}.\"\n            )\n        counts = np.sum(mask, axis=1)\n        if n > 0 and not np.all(counts == counts[0]):\n            raise ValueError(\n                \"Cannot filter keypoints with a 2D boolean mask where rows have \"\n                \"different numbers of True values. \"\n                \"All objects must select the same number of keypoints. \"\n                f\"Got counts per object: {counts.tolist()}\"\n            )\n        k = int(counts[0]) if n > 0 else 0\n        xy_selected = np.zeros((n, k, self.xy.shape[2]), dtype=self.xy.dtype)\n        keypoint_confidence_selected: npt.NDArray[np.float32] | None = None\n        if self.keypoint_confidence is not None:\n            keypoint_confidence_selected = cast(\n                npt.NDArray[np.float32],\n                np.zeros((n, k), dtype=self.keypoint_confidence.dtype),","sourceCodeStart":852,"sourceCodeEnd":888,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/key_points/core.py#L852-L888","documentation":"F1Score._make_empty_content() returns the shaped empty array for empty Detections per metric target and, like its siblings, ends with a defensive ValueError for any MetricTarget it does not know. Reachable only with version skew or injected enum values, and only when compute() processes empty Detections.","triggerScenarios":"An unsupported metric_target value combined with empty predictions/targets lists during F1Score.compute().","commonSituations":"Version-mismatched supervision installs or monkey-patched enums, surfaced when evaluating images with zero detections.","solutions":["Align the supervision version (reinstall/upgrade)","Restrict metric_target to supported members","Remove enum patches"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"SUPPORTED = {sv.MetricTarget.BOXES, sv.MetricTarget.MASKS, sv.MetricTarget.ORIENTED_BOUNDING_BOXES}\nassert target in SUPPORTED","typeGuard":"def is_supported_f1_target(target: sv.MetricTarget) -> bool:\n    return target in {sv.MetricTarget.BOXES, sv.MetricTarget.MASKS, sv.MetricTarget.ORIENTED_BOUNDING_BOXES}","tryCatchPattern":null,"preventionTips":["Validate the metric target once at startup","Run a minimal end-to-end metric call in CI to catch version-skew breakage early"],"tags":["metrics","f1-score","metric-target","defensive-code"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}