{"record":{"id":"fd9ef8652df4d295","repo":"roboflow/supervision","slug":"class-name-data-field-has-len-class-names-e","errorCode":null,"errorMessage":"'{CLASS_NAME_DATA_FIELD}' has {len(class_names)} entries but detections has {len(detections)} - the two must stay aligned.","messagePattern":"'(.+?)' 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":277,"sourceCode":"    Returns:\n        A list of text labels for each detection.\n\n    Raises:\n        ValueError: If `class_name` or `class_id` is present but its length\n            does not match the number of detections (e.g. `detections.data`\n            was mutated directly, bypassing `Detections` alignment checks).\n    \"\"\"\n    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],","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/annotators/utils.py#L259-L295","documentation":"Raised while resolving label text (util that backs `LabelAnnotator`/`RichLabelAnnotator`) when `detections.data[CLASS_NAME_DATA_FIELD]` has a different length than `detections` itself. `Detections.data` is normally kept aligned by the dataclass validator, but a caller that mutates `detections.data` directly (e.g. assigning a new array) can break alignment; the library fails loudly instead of dropping or duplicating labels.","triggerScenarios":"Doing `detections.data[CLASS_NAME_DATA_FIELD] = np.array(['cat', 'dog'])` after slicing detections down to 3 rows; assigning a class-name array built from the unsliced model result while `detections` was filtered via `detections[np.array([0, 2])]`; manually constructing Detections then appending to `.data` post-hoc.","commonSituations":"Post-processing pipelines that slice detections for zone filtering or confidence thresholds but update `data` from the pre-slice result; porting code that stored labels in a parallel Python list that drifted out of sync; debugging sessions that mutate `.data` interactively.","solutions":["Rebuild the data arrays after slicing: slice `detections` first, then assign `detections.data[CLASS_NAME_DATA_FIELD] = class_names[keep_mask]` with the same mask.","Set the field at construction time via the connector (most `from_*` connectors populate it from the model's class names) so alignment is enforced by the dataclass validator.","Use `Detections.__getitem__` (slicing) rather than rebuilding Detections manually — it re-indexes `.data` for you."],"exampleFix":"# before\nnames = result.names  # all detections\ndetections = detections[detections.class_id == 0]  # now shorter\ndetections.data[CLASS_NAME_DATA_FIELD] = names  # length mismatch -> ValueError\n\n# after\nkeep = detections.class_id == 0\ndetections.data[CLASS_NAME_DATA_FIELD] = detections.data[CLASS_NAME_DATA_FIELD][keep]\ndetections = detections[keep]","handlingStrategy":"validation","validationCode":"if CLASS_NAME_DATA_FIELD in detections.data:\n    assert len(detections.data[CLASS_NAME_DATA_FIELD]) == len(detections), (\n        \"class-name data drifted out of alignment with detections\"\n    )","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never mutate detections.data directly with arrays from a different-length source.","Set CLASS_NAME_DATA_FIELD at construction or via connectors so the dataclass validator enforces alignment.","Slice detections with detections[mask] — it re-indexes .data consistently."],"tags":["annotators","labels","alignment"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}