roboflow/supervision · error · ValueError

Either absolute_distance or relative_distance must be set.

Error message

Either absolute_distance or relative_distance must be set.

What it means

The keep-nearby-mask-components style helper needs a distance threshold to decide which connected components are 'near' the main one; the threshold comes either from relative_distance (fraction of the mask diagonal) or absolute_distance (pixels). If both are None there is no way to compute a threshold, so a ValueError is raised.

Source

Thrown at src/supervision/detection/utils/masks.py:483

    if num_labels <= 1:
        return cast(npt.NDArray[np.bool_], mask.copy())

    areas = stats[1:, cv2.CC_STAT_AREA]
    max_area = int(areas.max())
    candidates = 1 + np.flatnonzero(areas == max_area)
    # Use coordinates for equal-area ties so native and fallback labels agree.
    main_label = min(
        (int(label) for label in candidates),
        key=lambda label: (int(stats[label, 0]), int(stats[label, 1]), label),
    )

    if relative_distance is not None:
        diagonal = float(np.hypot(height, width))
        threshold = float(relative_distance) * diagonal
    elif absolute_distance is not None:
        threshold = float(absolute_distance)
    else:
        raise ValueError("Either absolute_distance or relative_distance must be set.")

    keep_labels: npt.NDArray[np.bool_] = np.zeros(num_labels, dtype=bool)
    keep_labels[main_label] = True

    if mode == "centroid":
        differences = centroids[1:] - centroids[main_label]
        distances = np.sqrt(np.sum(differences**2, axis=1))
        nearby = 1 + np.where(distances <= threshold)[0]
        keep_labels[nearby] = True
    elif mode == "edge":
        main_mask = labels == main_label
        if np.isnan(threshold) or threshold < 0:
            nearby_main = np.zeros_like(main_mask)
        elif np.isposinf(threshold):
            nearby_main = np.ones_like(main_mask)
        else:
            fixed_distances = _chamfer_distances(main_mask)
            distances = fixed_distances.astype(np.float32) / 65536

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Pass relative_distance (e.g. 0.2 = 20% of the diagonal) for resolution-independent behavior.
  2. Or pass absolute_distance in pixels when you know the expected component spacing.
  3. If wrapping the API, set your own default for one of the two parameters.

Example fix

# before
 filtered = filter_non_zero_mask_areas(mask=mask)  # no distance arg

# after
 filtered = filter_non_zero_mask_areas(
     mask=mask, relative_distance=0.2
 )
Defensive patterns

Strategy: validation

Validate before calling

if relative_distance is None and absolute_distance is None:
    relative_distance = 0.2  # app default: 20% of mask diagonal
result = filter_non_zero_mask_areas(
    mask=mask, relative_distance=relative_distance, absolute_distance=absolute_distance
)

Prevention

When it happens

Trigger: Calling the function with neither keyword argument, or passing relative_distance=None explicitly intending a default; both branches are checked and the else clause fires.

Common situations: Copy-pasting a call and deleting the 'unused' distance argument; wrapping the function and forwarding **kwargs where the distance key was never set; assuming absolute_distance defaults to something sane.

Related errors


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