{"record":{"id":"d37f99d90e141bcd","repo":"roboflow/supervision","slug":"all-or-none-of-the-name-fields-must-be-none","errorCode":null,"errorMessage":"All or none of the '{name}' fields must be None","messagePattern":"All or none of the '(.+?)' fields must be None","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/key_points/core.py","lineNumber":1280,"sourceCode":"                \"All KeyPoints must have the same number of keypoints per \"\n                f\"skeleton to be merged; got counts {sorted(keypoint_counts)}.\"\n            )\n\n        keypoint_depths = {key_points.xy.shape[2] for key_points in key_points_list}\n        if len(keypoint_depths) > 1:\n            raise ValueError(\n                \"All KeyPoints must have the same coordinate depth per \"\n                f\"skeleton to be merged; got depths {sorted(keypoint_depths)}.\"\n            )\n\n        xy = np.vstack([key_points.xy for key_points in key_points_list])\n\n        def stack_or_none(name: str) -> npt.NDArray[np.generic] | None:\n            values = [getattr(key_points, name) for key_points in key_points_list]\n            if all(value is None for value in values):\n                return None\n            if any(value is None for value in values):\n                raise ValueError(f\"All or none of the '{name}' fields must be None\")\n            return cast(npt.NDArray[np.generic], np.concatenate(values, axis=0))\n\n        class_id = cast(npt.NDArray[np.int_] | None, stack_or_none(\"class_id\"))\n        keypoint_confidence = cast(\n            npt.NDArray[np.float32] | None, stack_or_none(\"keypoint_confidence\")\n        )\n        detection_confidence = cast(\n            npt.NDArray[np.float32] | None, stack_or_none(\"detection_confidence\")\n        )\n        visible = cast(npt.NDArray[np.bool_] | None, stack_or_none(\"visible\"))\n\n        data = merge_data([key_points.data for key_points in key_points_list])\n\n        return cls(\n            xy=xy,\n            class_id=class_id,\n            keypoint_confidence=keypoint_confidence,\n            detection_confidence=detection_confidence,","sourceCodeStart":1262,"sourceCodeEnd":1298,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/key_points/core.py#L1262-L1298","documentation":"Raised inside KeyPoints.merge() by the stack_or_none helper for optional fields (class_id, keypoint_confidence, detection_confidence, visible). Merging concatenates these arrays along axis 0, which is only well-defined if every input provides the field or every input omits it; a mix would leave undefined rows for some skeletons.","triggerScenarios":"Calling sv.KeyPoints.merge([kp_a, kp_b]) where kp_a has class_id set but kp_b.class_id is None (or the same mismatch for keypoint_confidence, detection_confidence, or visible).","commonSituations":"Merging predictions from two models where one connector populates detection_confidence and the other does not; merging manually-constructed KeyPoints with model-produced ones; mixing from_mediapipe output (no class_id) with from_ultralytics output (has class_id).","solutions":["Fill the missing field on all inputs before merging (e.g. assign a default class_id array of zeros or ones).","Drop the field from all inputs so none has it (set to None uniformly).","Merge only KeyPoints from the same connector so optional fields are consistently populated."],"exampleFix":"// before\nmerged = sv.KeyPoints.merge([kp_with_class_id, kp_without_class_id])\n\n// after\n# give the field a default so all inputs provide it\nn = len(kp_without_class_id)\nkp_without_class_id.class_id = np.zeros(n, dtype=np.int64)\nmerged = sv.KeyPoints.merge([kp_with_class_id, kp_without_class_id])","handlingStrategy":"validation","validationCode":"FIELDS = (\"class_id\", \"keypoint_confidence\", \"detection_confidence\", \"visible\")\n\ndef uniform_fields(kps: list[sv.KeyPoints]) -> bool:\n    for f in FIELDS:\n        if len({getattr(kp, f) is None for kp in kps}) > 1:\n            return False\n    return True\n\nassert uniform_fields(kps), \"Optional fields must be all-set or all-None before merge\"","typeGuard":"def mergeable(kps: list[sv.KeyPoints]) -> bool:\n    for f in (\"class_id\", \"keypoint_confidence\", \"detection_confidence\", \"visible\"):\n        flags = {getattr(kp, f) is None for kp in kps}\n        if len(flags) > 1:\n            return False\n    return True","tryCatchPattern":"try:\n    merged = sv.KeyPoints.merge(kps)\nexcept ValueError as e:\n    if \"must be None\" in str(e):\n        # fill defaults for missing fields, then retry once\n        raise\n    raise","preventionTips":["Construct all KeyPoints through one factory that always sets the same optional fields.","Before merging, check each optional field is either set on every KeyPoints or None on every one.","Default missing class_id to zeros when semantics allow (single-class pipelines)."],"tags":["keypoints","merge","validation","optional-fields"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}