{"record":{"id":"6ab4182b610f22d5","repo":"roboflow/supervision","slug":"class-id-has-len-detections-class-id-entries","errorCode":null,"errorMessage":"'class_id' has {len(detections.class_id)} entries but detections has {len(detections)} - the two must stay aligned.","messagePattern":"'class_id' has (.+?) entries but detections has (.+?) - the two must stay aligned\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/annotators/utils.py","lineNumber":285,"sourceCode":"    if custom_labels is not None:\n        return custom_labels\n\n    if CLASS_NAME_DATA_FIELD in detections.data:\n        class_names = detections.data[CLASS_NAME_DATA_FIELD]\n        # `Detections.data` is normally kept aligned with `xyxy` by the\n        # dataclass's own validation, but a caller can bypass it by mutating\n        # `detections.data` directly. Fail loudly rather than silently\n        # dropping or duplicating labels.\n        if len(class_names) != len(detections):\n            raise ValueError(\n                f\"'{CLASS_NAME_DATA_FIELD}' has {len(class_names)} entries \"\n                f\"but detections has {len(detections)} - the two must stay \"\n                \"aligned.\"\n            )\n        return [str(v) for v in class_names]\n    if detections.class_id is not None:\n        if len(detections.class_id) != len(detections):\n            raise ValueError(\n                f\"'class_id' has {len(detections.class_id)} entries but \"\n                f\"detections has {len(detections)} - the two must stay \"\n                \"aligned.\"\n            )\n        return [str(v) for v in detections.class_id]\n    return [str(i) for i in range(len(detections))]\n\n\ndef snap_boxes(\n    xyxy: npt.NDArray[np.float32],\n    resolution_wh: tuple[int, int],\n) -> npt.NDArray[np.float32]:\n    \"\"\"\n    Shifts `label` bounding boxes into the frame so that they are fully contained\n    within the given resolution, prioritizing the top/left edge.\n    Unlike `clip_boxes`, this function does not crop boxes.\n    It moves them entirely if they exceed the frame boundaries.\n","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/annotators/utils.py#L267-L303","documentation":"Raised while resolving label text when `detections.class_id` exists but its length differs from `len(detections)`. This indicates the internal invariant `len(class_id) == len(xyxy)` was broken, almost always by direct mutation of `detections.class_id` after construction, since the Detections dataclass normally validates alignment.","triggerScenarios":"Assigning `detections.class_id = new_class_ids` where `new_class_ids` came from the unfiltered model output while `detections` was sliced; constructing `Detections(xyxy=..., class_id=...)` with mismatched array lengths is blocked by the validator, so the error surfaces when the field is replaced afterwards.","commonSituations":"Remapping class ids after filtering detections (e.g. merging classes) but computing the mapping array from the pre-filter result; interactive sessions that overwrite `.class_id`; copying fields between two Detections objects of different sizes.","solutions":["Recompute the replacement array from the same filter mask used for the detections slice.","Never overwrite `.class_id` with arrays from a different-length source; rebuild a new `Detections` via `dataclasses.replace` or a connector instead.","Add an assertion `assert len(detections.class_id) == len(detections)` right after any manual field assignment in your pipeline."],"exampleFix":"# before\nnew_ids = np.array([0, 1, 2])          # from unfiltered result\ndetections = detections[:2]             # len 2\ndetections.class_id = new_ids           # len 3 -> ValueError at annotate time\n\n# after\ndetections = detections[:2]\ndetections.class_id = np.array([0, 1])  # aligned with len(detections)","handlingStrategy":"validation","validationCode":"if detections.class_id is not None:\n    assert len(detections.class_id) == len(detections), \"class_id misaligned\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["After any manual field assignment, assert alignment with len(detections).","Prefer rebuilding Detections (dataclasses.replace / connector) over overwriting fields."],"tags":["annotators","labels","alignment"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}