roboflow/supervision · error · ValueError

All or none of the '{name}' fields must be None

Error message

All or none of the '{name}' fields must be None

What it means

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.

Source

Thrown at src/supervision/key_points/core.py:1280

                "All KeyPoints must have the same number of keypoints per "
                f"skeleton to be merged; got counts {sorted(keypoint_counts)}."
            )

        keypoint_depths = {key_points.xy.shape[2] for key_points in key_points_list}
        if len(keypoint_depths) > 1:
            raise ValueError(
                "All KeyPoints must have the same coordinate depth per "
                f"skeleton to be merged; got depths {sorted(keypoint_depths)}."
            )

        xy = np.vstack([key_points.xy for key_points in key_points_list])

        def stack_or_none(name: str) -> npt.NDArray[np.generic] | None:
            values = [getattr(key_points, name) for key_points in key_points_list]
            if all(value is None for value in values):
                return None
            if any(value is None for value in values):
                raise ValueError(f"All or none of the '{name}' fields must be None")
            return cast(npt.NDArray[np.generic], np.concatenate(values, axis=0))

        class_id = cast(npt.NDArray[np.int_] | None, stack_or_none("class_id"))
        keypoint_confidence = cast(
            npt.NDArray[np.float32] | None, stack_or_none("keypoint_confidence")
        )
        detection_confidence = cast(
            npt.NDArray[np.float32] | None, stack_or_none("detection_confidence")
        )
        visible = cast(npt.NDArray[np.bool_] | None, stack_or_none("visible"))

        data = merge_data([key_points.data for key_points in key_points_list])

        return cls(
            xy=xy,
            class_id=class_id,
            keypoint_confidence=keypoint_confidence,
            detection_confidence=detection_confidence,

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Fill the missing field on all inputs before merging (e.g. assign a default class_id array of zeros or ones).
  2. Drop the field from all inputs so none has it (set to None uniformly).
  3. Merge only KeyPoints from the same connector so optional fields are consistently populated.

Example fix

// before
merged = sv.KeyPoints.merge([kp_with_class_id, kp_without_class_id])

// after
# give the field a default so all inputs provide it
n = len(kp_without_class_id)
kp_without_class_id.class_id = np.zeros(n, dtype=np.int64)
merged = sv.KeyPoints.merge([kp_with_class_id, kp_without_class_id])
Defensive patterns

Strategy: validation

Validate before calling

FIELDS = ("class_id", "keypoint_confidence", "detection_confidence", "visible")

def uniform_fields(kps: list[sv.KeyPoints]) -> bool:
    for f in FIELDS:
        if len({getattr(kp, f) is None for kp in kps}) > 1:
            return False
    return True

assert uniform_fields(kps), "Optional fields must be all-set or all-None before merge"

Type guard

def mergeable(kps: list[sv.KeyPoints]) -> bool:
    for f in ("class_id", "keypoint_confidence", "detection_confidence", "visible"):
        flags = {getattr(kp, f) is None for kp in kps}
        if len(flags) > 1:
            return False
    return True

Try / catch

try:
    merged = sv.KeyPoints.merge(kps)
except ValueError as e:
    if "must be None" in str(e):
        # fill defaults for missing fields, then retry once
        raise
    raise

Prevention

When it happens

Trigger: 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).

Common situations: 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).

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/d37f99d90e141bcd. Report an issue: GitHub.