roboflow/supervision · error · ValueError
xyxyxyxy must have shape (N, 4, 2); got {xyxyxyxy.shape}
Error message
xyxyxyxy must have shape (N, 4, 2); got {xyxyxyxy.shape} What it means
Raised by xyxyxyxy_to_xyxy when the input oriented-box corner array is not shaped (N, 4, 2). The conversion takes per-box min/max over the corner axis, which only makes sense when every box contributes exactly 4 (x, y) pairs; any other layout would produce wrong axis-aligned bounds.
Source
Thrown at src/supervision/detection/utils/boxes.py:311
ValueError: If `xyxyxyxy` does not have shape `(N, 4, 2)`.
Examples:
```pycon
>>> import numpy as np
>>> import supervision as sv
>>> corners = np.array([
... [[0, 0], [10, 0], [10, 5], [0, 5]],
... [[5, 5], [15, 5], [15, 10], [5, 10]],
... ], dtype=np.float32)
>>> sv.xyxyxyxy_to_xyxy(corners)
array([[ 0., 0., 10., 5.],
[ 5., 5., 15., 10.]], dtype=float32)
```
"""
xyxyxyxy = cast(npt.NDArray[np.number], np.asarray(xyxyxyxy))
if xyxyxyxy.ndim != 3 or xyxyxyxy.shape[-2:] != (4, 2):
raise ValueError(f"xyxyxyxy must have shape (N, 4, 2); got {xyxyxyxy.shape}")
x_min = xyxyxyxy[..., 0].min(axis=-1)
y_min = xyxyxyxy[..., 1].min(axis=-1)
x_max = xyxyxyxy[..., 0].max(axis=-1)
y_max = xyxyxyxy[..., 1].max(axis=-1)
return cast(npt.NDArray[np.number], np.stack([x_min, y_min, x_max, y_max], axis=-1))
# Anchor position -> (sx, sy) offset from the box center, in units of the box
# half-width and half-height. Image coordinates, so +y points down.
_ANCHOR_OFFSETS: dict[Position, tuple[float, float]] = {
Position.CENTER: (0.0, 0.0),
Position.CENTER_LEFT: (-1.0, 0.0),
Position.CENTER_RIGHT: (1.0, 0.0),
Position.TOP_CENTER: (0.0, -1.0),
Position.BOTTOM_CENTER: (0.0, 1.0),
Position.TOP_LEFT: (-1.0, -1.0),
Position.TOP_RIGHT: (1.0, -1.0),
Position.BOTTOM_LEFT: (-1.0, 1.0),View on GitHub (pinned to 7f254d9784)
Solutions
- Reshape flattened 8-number boxes: corners = flat.reshape(-1, 4, 2).
- Add a batch axis for a single box: corners = box[np.newaxis].
- If you have axis-aligned xyxy boxes, you do not need this function — use the array as is.
Example fix
# before corners = model_output.reshape(-1, 8) sv.xyxyxyxy_to_xyxy(corners) # ValueError # after corners = model_output.reshape(-1, 4, 2) sv.xyxyxyxy_to_xyxy(corners)
Defensive patterns
Strategy: type-guard
Validate before calling
import numpy as np
def to_xyxyxyxy(a) -> np.ndarray:
a = np.asarray(a)
if a.ndim == 2 and a.shape[-1] == 8:
a = a.reshape(-1, 4, 2)
if a.ndim == 2 and a.shape == (4, 2):
a = a[np.newaxis]
assert a.ndim == 3 and a.shape[-2:] == (4, 2), f'bad shape {a.shape}'
return a
xyxy = sv.xyxyxyxy_to_xyxy(to_xyxyxyxy(corners)) Type guard
def is_xyxyxyxy(a) -> bool:
a = np.asarray(a)
return a.ndim == 3 and a.shape[-2:] == (4, 2) Prevention
- Standardize on (N, 4, 2) for all oriented-box arrays in your codebase; reshape once at ingestion.
- Do not pass xyxy (N, 4) arrays to oriented-box converters.
When it happens
Trigger: Passing a single un-batched box of shape (4, 2); passing an (N, 8) or (N, 4, 4) flattened layout; passing a ragged Python list whose np.asarray result is object-dtype or 2-D.
Common situations: Models that emit OBB corners flattened as 8 numbers per box (common in YOLO-OBB outputs before reshaping); forgetting the batch dimension for one box; mixing up the xyxy (N, 4) and xyxyxyxy (N, 4, 2) conventions.
Related errors
- corners must have shape (N, 4, 2); got {corners.shape}
- xyxyxyxy must have shape (N, 4, 2); got {corners.shape}
- `{name}` has shape {arr.shape}; expected (N, 4, 2) — each bo
- `{name}` has shape {arr.shape}; expected (N, 8) for flat YOL
- `{name}` has shape {arr.shape}; expected (N, 5) or (N, 6).
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/de46f820519e8810.
Report an issue: GitHub.