roboflow/supervision · error · ValueError

visible first dimension must be {n}, but got shape {actual_s

Error message

visible first dimension must be {n}, but got shape {actual_shape}

What it means

Raised by supervision.validators._validate_visible when visible is a 2D array but its first dimension does not equal n, the number of key-point objects in xy. Every object row must have a corresponding visibility row.

Source

Thrown at src/supervision/validators/__init__.py:250

def validate_xy(xy: Any, n: int, m: int) -> None:
    void(xy, n, m)


def _validate_visible(visible: Any, n: int, m: int) -> None:
    """Validate per-keypoint visibility mask.

    Expects a 2D bool ``np.ndarray`` with shape ``(n, m)``.
    """
    if visible is None:
        return
    actual_shape = str(getattr(visible, "shape", None))
    if not isinstance(visible, np.ndarray) or visible.ndim != 2:
        raise ValueError(
            "visible must be a 2D np.ndarray with shape (n, m), but "
            f"got shape {actual_shape}"
        )
    if visible.shape[0] != n:
        raise ValueError(
            f"visible first dimension must be {n}, but got shape {actual_shape}"
        )
    if n > 0 and visible.shape[1] != m:
        raise ValueError(
            f"visible second dimension must be {m}, but got shape {actual_shape}"
        )


def _validate_detections_fields(
    xyxy: Any,
    mask: Any,
    class_id: Any,
    confidence: Any,
    tracker_id: Any,
    data: dict[str, Any],
) -> None:
    _validate_xyxy(xyxy)
    n = len(xyxy)

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Rebuild or slice visible so visible.shape[0] == xy.shape[0].
  2. Apply the same object-index mask to both: xy = xy[idx]; visible = visible[idx].
  3. Tile a shared mask: visible = np.tile(single_mask, (xy.shape[0], 1)).

Example fix

# before
kp = KeyPoints(xy=xy, visible=vis)  # xy:(3,17,2), vis:(1,17)

# after
kp = KeyPoints(xy=xy, visible=np.tile(vis, (xy.shape[0], 1)))
Defensive patterns

Strategy: validation

Validate before calling

n = xy.shape[0]
visible = np.asarray(visible, dtype=bool)
assert visible.shape[0] == n, f"visible rows {visible.shape[0]} != objects {n}"
kp = KeyPoints(xy=xy, visible=visible)

Type guard

def visible_rows_match(visible: np.ndarray, xy: np.ndarray) -> bool:
    return visible.ndim == 2 and visible.shape[0] == xy.shape[0]

Prevention

When it happens

Trigger: Constructing KeyPoints with xy of shape (3, 17, 2) but visible of shape (2, 17) or (1, 17).

Common situations: Using one visibility mask for a multi-person frame; filtering xy objects without filtering visible rows in sync; off-by-one after dropping an object from xy.

Related errors


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