{"record":{"id":"40ff817f784b929f","repo":"roboflow/supervision","slug":"xyxyxyxy-must-have-shape-n-4-2-got-corners-s","errorCode":null,"errorMessage":"xyxyxyxy must have shape (N, 4, 2); got {corners.shape}","messagePattern":"xyxyxyxy must have shape \\(N, 4, 2\\); got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/utils/boxes.py","lineNumber":385,"sourceCode":"        The anchor always lies on the box; the effect is cosmetic for static\n        images but visible on rotating objects in video.\n\n    Examples:\n        ```pycon\n        >>> import numpy as np\n        >>> from supervision.detection.utils.boxes import _oriented_box_anchors\n        >>> from supervision.geometry.core import Position\n        >>> corners = np.array(\n        ...     [[[0, 0], [10, 0], [10, 4], [0, 4]]], dtype=np.float32\n        ... )\n        >>> _oriented_box_anchors(corners, Position.BOTTOM_CENTER)\n        array([[5., 4.]])\n\n        ```\n    \"\"\"\n    corners = np.asarray(xyxyxyxy, dtype=np.float64)\n    if corners.ndim != 3 or corners.shape[-2:] != (4, 2):\n        raise ValueError(f\"xyxyxyxy must have shape (N, 4, 2); got {corners.shape}\")\n    if anchor not in _ANCHOR_OFFSETS:\n        raise ValueError(f\"{anchor} is not supported.\")\n    sx, sy = _ANCHOR_OFFSETS[anchor]\n\n    center = corners.mean(axis=1)\n    # Two perpendicular half-side vectors per box.\n    half_side_a = (corners[:, 1] - corners[:, 0]) / 2\n    half_side_b = (corners[:, 2] - corners[:, 1]) / 2\n\n    # Map each box's own sides onto the image axes: the side more aligned with\n    # the x-axis plays the role of width, the other of height. This makes the\n    # offsets collapse to the axis-aligned frame when the box is not rotated.\n    is_width = np.abs(half_side_a[:, 0]) >= np.abs(half_side_b[:, 0])\n    width = np.where(is_width[:, None], half_side_a, half_side_b)\n    height = np.where(is_width[:, None], half_side_b, half_side_a)\n    # Point width toward +x and height toward +y so the offset signs are stable.\n    width = np.where((width[:, 0] < 0)[:, None], -width, width)\n    height = np.where((height[:, 1] < 0)[:, None], -height, height)","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/utils/boxes.py#L367-L403","documentation":"Raised by the private helper _oriented_box_anchors in boxes.py when the corner array is not shaped (N, 4, 2). The helper computes box centers and half-side vectors by indexing corners[:, 1], corners[:, 2], etc., so exactly 4 corner points per box are required. Note the message names the parameter 'xyxyxyxy' even though the local variable is 'corners' — same requirement either way.","triggerScenarios":"Calling _oriented_box_anchors (directly, or indirectly through an annotator that places labels on rotated boxes) with an un-batched (4, 2) array, an (N, 8) flattened array, or an array with the wrong corner count.","commonSituations":"Custom annotation code that holds OBB corners in a non-standard layout; downstream code reshaping model output incorrectly before annotation; usually reached via BoxAnnotator/LabelAnnotator with oriented detections rather than called directly.","solutions":["Reshape input to (N, 4, 2): flat.reshape(-1, 4, 2) or box[np.newaxis] for a single box.","If you hit this via an annotator, fix the ORIENTED_BOX_COORDINATES data field attached to your Detections so it has shape (N, 4, 2).","Prefer the public API path (annotators) instead of calling the underscore-prefixed helper directly."],"exampleFix":"# before\nanchors = _oriented_box_anchors(box_4x2, Position.BOTTOM_CENTER)  # ValueError\n\n# after\nanchors = _oriented_box_anchors(box_4x2[np.newaxis], Position.BOTTOM_CENTER)","handlingStrategy":"type-guard","validationCode":"corners = np.asarray(corners, dtype=np.float64).reshape(-1, 4, 2)\nanchors = _oriented_box_anchors(corners, position)","typeGuard":"def is_xyxyxyxy(a) -> bool:\n    a = np.asarray(a)\n    return a.ndim == 3 and a.shape[-2:] == (4, 2)","tryCatchPattern":null,"preventionTips":["Avoid the private underscore helper; go through public annotators.","Ensure Detections.data[ORIENTED_BOX_COORDINATES] always has shape (N, 4, 2)."],"tags":["oriented-bounding-box","anchors","numpy","shape-validation","internal-api","valueerror"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}