{"record":{"id":"073a667b0f5d7111","repo":"roboflow/supervision","slug":"visible-must-be-a-2d-np-ndarray-with-shape-n-m","errorCode":null,"errorMessage":"visible must be a 2D np.ndarray with shape (n, m), but got shape {actual_shape}","messagePattern":"visible must be a 2D np\\.ndarray with shape \\(n, m\\), but got shape (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/validators/__init__.py","lineNumber":245,"sourceCode":"@deprecated(  # type: ignore[untyped-decorator]\n    target=_validate_xy,\n    deprecated_in=\"0.29.0\",\n    remove_in=\"0.32.0\",\n)\ndef validate_xy(xy: Any, n: int, m: int) -> None:\n    void(xy, n, m)\n\n\ndef _validate_visible(visible: Any, n: int, m: int) -> None:\n    \"\"\"Validate per-keypoint visibility mask.\n\n    Expects a 2D bool ``np.ndarray`` with shape ``(n, m)``.\n    \"\"\"\n    if visible is None:\n        return\n    actual_shape = str(getattr(visible, \"shape\", None))\n    if not isinstance(visible, np.ndarray) or visible.ndim != 2:\n        raise ValueError(\n            \"visible must be a 2D np.ndarray with shape (n, m), but \"\n            f\"got shape {actual_shape}\"\n        )\n    if visible.shape[0] != n:\n        raise ValueError(\n            f\"visible first dimension must be {n}, but got shape {actual_shape}\"\n        )\n    if n > 0 and visible.shape[1] != m:\n        raise ValueError(\n            f\"visible second dimension must be {m}, but got shape {actual_shape}\"\n        )\n\n\ndef _validate_detections_fields(\n    xyxy: Any,\n    mask: Any,\n    class_id: Any,\n    confidence: Any,","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/validators/__init__.py#L227-L263","documentation":"Raised by supervision.validators._validate_visible (KeyPoints constructor path) when the visible argument is not None and is not a 2D np.ndarray. visible is a boolean mask of shape (n, m) marking which of the m keypoints are drawn/considered for each of the n objects.","triggerScenarios":"Passing visible as a Python list of lists, a 1D array of length m, or a 3D array when constructing KeyPoints.","commonSituations":"Building the visibility mask from model output without np.asarray; reusing a per-object visibility vector for a batch of objects; confusing visible with confidence arrays.","solutions":["Convert to a 2D bool array: visible=np.asarray(mask, dtype=bool).reshape(n, m).","Broadcast a single-object mask: np.tile(mask, (n, 1)).","Leave visible=None to let KeyPoints infer visibility from coordinate data."],"exampleFix":"# before\nkp = KeyPoints(xy=xy, visible=[[True]*17])  # nested list -> ValueError\n\n# after\nkp = KeyPoints(xy=xy, visible=np.full((1, 17), True, dtype=bool))","handlingStrategy":"validation","validationCode":"n, m = xy.shape[0], xy.shape[1]\nvisible = None if visible is None else np.asarray(visible, dtype=bool).reshape(n, m)\nkp = KeyPoints(xy=xy, visible=visible)","typeGuard":"def is_valid_visible(visible: Any) -> bool:\n    return visible is None or (\n        isinstance(visible, np.ndarray) and visible.ndim == 2\n    )","tryCatchPattern":null,"preventionTips":["Always np.asarray(visible, dtype=bool) before passing.","Build the mask with explicit (n, m) shape, not nested lists.","Omit visible when KeyPoints can infer it from xy."],"tags":["keypoints","validation","shape","mask"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}