{"record":{"id":"ab70fe1739a1d9b1","repo":"roboflow/supervision","slug":"detections-class-id-must-be-given-for-operation-n","errorCode":null,"errorMessage":"Detections class_id must be given for {operation_name} to be executed. If you intended to perform class agnostic {operation_name} set class_agnostic=True.","messagePattern":"Detections class_id must be given for (.+?) to be executed\\. If you intended to perform class agnostic (.+?) set class_agnostic=True\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/core.py","lineNumber":2989,"sourceCode":"        )\n        return new\n\n    def _build_nms_predictions(\n        self, class_agnostic: bool, operation_name: str\n    ) -> npt.NDArray[np.floating]:\n        \"\"\"Stack xyxy + confidence (+ class_id) for NMS/NMM/Soft-NMS dispatch.\n\n        Callers must already have verified `self.confidence is not None`.\n        \"\"\"\n        if class_agnostic:\n            return cast(\n                npt.NDArray[np.floating],\n                np.hstack(\n                    (self.xyxy, cast(np.ndarray, self.confidence).reshape(-1, 1))\n                ),\n            )\n        if self.class_id is None:\n            raise ValueError(\n                f\"Detections class_id must be given for {operation_name} to be \"\n                f\"executed. If you intended to perform class agnostic \"\n                f\"{operation_name} set class_agnostic=True.\"\n            )\n        return cast(\n            npt.NDArray[np.floating],\n            np.hstack(\n                (\n                    self.xyxy,\n                    cast(np.ndarray, self.confidence).reshape(-1, 1),\n                    self.class_id.reshape(-1, 1),\n                )\n            ),\n        )\n\n    def with_nms(\n        self,\n        threshold: float = 0.5,","sourceCodeStart":2971,"sourceCodeEnd":3007,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/core.py#L2971-L3007","documentation":"The internal _build_nms_predictions helper stacks xyxy, confidence, and (unless class_agnostic) class_id for the NMS/NMM/Soft-NMS dispatchers. Class-aware suppression needs class_id to compare boxes within the same class; if class_id is None and class_agnostic=False, it raises this error naming the operation that failed.","triggerScenarios":"Calling detections.with_nms(threshold=...), with_soft_nms(...), or with_nmm(...) on a Detections whose class_id is None while class_agnostic is False (the default). This happens with outputs from connectors that don't populate class_id (e.g. some VLM/OCR connectors like from_paddledetection_ocr or from_easyocr, or hand-built cls(xyxy=..., confidence=...)).","commonSituations":"Building Detections manually from raw boxes+scores and forgetting class_id; applying with_nms to OCR/VLM results that carry only class_name in data; processing model variants that return no class predictions.","solutions":["Pass class_agnostic=True if cross-class suppression is acceptable: detections.with_nms(threshold=0.5, class_agnostic=True).","Populate class_id before suppression if you have class info (even a zeros array for a single class): cls(xyxy=..., confidence=..., class_id=np.zeros(len(xyxy), dtype=int)).","For OCR text duplicates, consider deduplicating on data[CLASS_NAME_DATA_FIELD] yourself instead of class-aware NMS."],"exampleFix":"# before\ndetections = sv.Detections(xyxy=boxes, confidence=scores)\nclean = detections.with_nms(threshold=0.5)  # ValueError: class_id missing\n\n# after\ndetections = sv.Detections(\n    xyxy=boxes,\n    confidence=scores,\n    class_id=np.zeros(len(boxes), dtype=int),\n)\nclean = detections.with_nms(threshold=0.5)\n# or: clean = detections.with_nms(threshold=0.5, class_agnostic=True)","handlingStrategy":"validation","validationCode":"def can_run_class_aware_nms(dets: sv.Detections) -> bool:\n    return dets.class_id is not None\n\nclean = (\n    detections.with_nms(threshold=0.5)\n    if can_run_class_aware_nms(detections)\n    else detections.with_nms(threshold=0.5, class_agnostic=True)\n)","typeGuard":"def has_class_id(dets: sv.Detections) -> bool:\n    return dets.class_id is not None","tryCatchPattern":"try:\n    clean = detections.with_nms(threshold=0.5)\nexcept ValueError as e:\n    if 'class_agnostic' in str(e):\n        clean = detections.with_nms(threshold=0.5, class_agnostic=True)\n    else:\n        raise","preventionTips":["Always construct Detections with class_id (zeros for single-class)","Decide class_agnostic policy per pipeline stage","Check .class_id is not None before suppression on VLM/OCR outputs"],"tags":["nms","class-id","class-agnostic","detections"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}