roboflow/supervision · error · ValueError

visible second dimension must be {m}, but got shape {actual_

Error message

visible second dimension must be {m}, but got shape {actual_shape}

What it means

Raised by supervision.validators._validate_visible when visible's second dimension does not equal m, the number of keypoints per object expected from xy. The check runs only when n > 0, because with zero objects m cannot be cross-validated.

Source

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

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)
    _validate_mask(mask, n)
    _validate_class_id(class_id, n)
    _validate_confidence(confidence, n)
    _validate_tracker_id(tracker_id, n)

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Derive m from xy: m = xy.shape[1], and build visible with exactly m columns.
  2. Trim/pad the mask to match: visible = visible[:, :xy.shape[1]].
  3. Use None for visible when unsure, and let KeyPoints infer visibility.

Example fix

# before
kp = KeyPoints(xy=xy, visible=vis_13)  # xy has 17 points

# after
kp = KeyPoints(xy=xy, visible=vis_13[:, :xy.shape[1]])  # or rebuild with 17 cols
Defensive patterns

Strategy: validation

Validate before calling

m = xy.shape[1]
visible = np.asarray(visible, dtype=bool)[:, :m]
kp = KeyPoints(xy=xy, visible=visible)

Type guard

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

Prevention

When it happens

Trigger: Constructing KeyPoints with xy of shape (1, 17, 2) but a visible mask of shape (1, 13) — e.g. a COCO-17 model with a 13-point visibility vector.

Common situations: Mixing keypoint schemas (COCO 17 vs. MPII 16 vs. custom 13); hardcoding m from a different pose model; keeping a stale visibility mask after switching skeletons.

Related errors


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