roboflow/supervision · error · ValueError

Field '{attribute}' should be consistently None or not None

Error message

Field '{attribute}' should be consistently None or not None in both Detections.

What it means

_validate_fields_both_defined_or_none checks every instance attribute of two Detections (via get_instance_variables) and requires each field to be None in both or set in both. Merging operations (merge_object_detection_pair etc.) can only combine like-shaped inputs, so any mismatch — e.g. one has tracker_id and the other doesn't — raises this ValueError naming the offending attribute.

Source

Thrown at src/supervision/detection/core.py:3531

def _validate_fields_both_defined_or_none(
    detections_1: Detections, detections_2: Detections
) -> None:
    """
    Verify that for each optional field in the Detections, both instances either have
    the field set to None or both have it set to non-None values.

    `data` field is ignored.

    Raises:
        ValueError: If one field is None and the other is not, for any of the fields.
    """
    attributes = get_instance_variables(detections_1)
    for attribute in attributes:
        value_1 = getattr(detections_1, attribute)
        value_2 = getattr(detections_2, attribute)

        if (value_1 is None) != (value_2 is None):
            raise ValueError(
                f"Field '{attribute}' should be consistently None or not None in both "
                "Detections."
            )


@deprecated(  # type: ignore[untyped-decorator]
    target=_validate_fields_both_defined_or_none,
    deprecated_in="0.29.0",
    remove_in="0.32.0",
)
def validate_fields_both_defined_or_none(
    detections_1: Detections, detections_2: Detections
) -> None:
    void(detections_1, detections_2)

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Align fields before merging: either strip the extra field (d.tracker_id = None) or populate the missing one (uniform confidence = np.ones(len(d)), zeros class_id).
  2. When one side is empty, use Detections.empty() from the same code path or explicitly None out mismatched fields on both.
  3. Check the named attribute in the message — it tells you exactly which field mismatched.

Example fix

# before
merged = merge_object_detection_pair(detect_det, vlm_det)
# detect_det.confidence is array, vlm_det.confidence is None -> ValueError

# after
if vlm_det.confidence is None and detect_det.confidence is not None:
    vlm_det.confidence = np.ones(len(vlm_det), dtype=float)
merged = merge_object_detection_pair(detect_det, vlm_det)
Defensive patterns

Strategy: validation

Validate before calling

def align_detection_fields(d1: sv.Detections, d2: sv.Detections):
    for name in ('confidence', 'class_id', 'tracker_id', 'mask'):
        v1, v2 = getattr(d1, name, None), getattr(d2, name, None)
        if (v1 is None) != (v2 is None):
            if v1 is None:
                setattr(d1, name, np.ones(len(d1)) if name == 'confidence' else None)
                # populate or strip per your policy
    return d1, d2

d1, d2 = align_detection_fields(d1, d2)
merged = merge_object_detection_pair(d1, d2)

Type guard

def fields_compatible(d1: sv.Detections, d2: sv.Detections) -> bool:
    for name in ('confidence', 'class_id', 'tracker_id', 'mask'):
        if (getattr(d1, name, None) is None) != (getattr(d2, name, None) is None):
            return False
    return True

Try / catch

try:
    merged = merge_object_detection_pair(d1, d2)
except ValueError as e:
    if 'consistently None' in str(e):
        field = str(e).split("'")[1]
        setattr(d2, field, getattr(d1, field))  # or None-out both
        merged = merge_object_detection_pair(d1, d2)
    else:
        raise

Prevention

When it happens

Trigger: Calling merge_object_detection_pair(d1, d2) (or group/merge flows that call this validator) where d1.confidence is set but d2.confidence is None, one has mask and the other doesn't, one has tracker_id and the other doesn't, etc. The 'data' field is ignored.

Common situations: Merging detections from two different model types (detector with confidence vs. VLM without); merging tracked and untracked Detections; one side passed through Detections.empty() or a filter that dropped fields; mixing from_inference output with hand-built Detections.

Related errors


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