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

  1. Reshape flattened 8-number boxes: corners = flat.reshape(-1, 4, 2).
  2. Add a batch axis for a single box: corners = box[np.newaxis].
  3. 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

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


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