roboflow/supervision · error · ValueError

First dimension of np.ndarray for key '{key}' must have size

Error message

First dimension of np.ndarray for key '{key}' must have size {n}

What it means

Raised when a `data` dictionary entry is a multi-dimensional np.ndarray (e.g. masks of shape (n, H, W) or oriented boxes) whose first dimension does not equal the number of detections `n`. The first axis is the per-detection axis and must line up with `xyxy`. Later dimensions (H, W, point counts) are unconstrained by this check.

Source

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

@deprecated(  # type: ignore[untyped-decorator]
    target=_validate_tracker_id,
    deprecated_in="0.29.0",
    remove_in="0.32.0",
)
def validate_tracker_id(tracker_id: Any, n: int) -> None:
    void(tracker_id, n)


def _validate_data(data: dict[str, Any], n: int) -> None:
    for key, value in data.items():
        if isinstance(value, list):
            if len(value) != n:
                raise ValueError(f"Length of list for key '{key}' must be {n}")
        elif isinstance(value, np.ndarray):
            if value.ndim == 1 and value.shape[0] != n:
                raise ValueError(f"Shape of np.ndarray for key '{key}' must be ({n},)")
            elif value.ndim > 1 and value.shape[0] != n:
                raise ValueError(
                    f"First dimension of np.ndarray for key '{key}' must have size {n}"
                )
        else:
            raise ValueError(f"Value for key '{key}' must be a list or np.ndarray")


@deprecated(  # type: ignore[untyped-decorator]
    target=_validate_data,
    deprecated_in="0.29.0",
    remove_in="0.32.0",
)
def validate_data(data: dict[str, Any], n: int) -> None:
    void(data, n)


def _validate_xy(xy: Any, n: int, m: int) -> None:
    expected_shape = f"({n}, {m}, 2) or ({n}, {m}, 3)"
    actual_shape = str(getattr(xy, "shape", None))

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Verify `arr.shape[0] == detections.xyxy.shape[0]` for every multi-dim `data` value before constructing `Detections`.
  2. Apply the identical index/mask to `xyxy` and to each `data` array when filtering detections.
  3. If the arrays come from different pipeline stages, re-index them from a shared key (e.g. tracker_id) before attaching.

Example fix

# before
mask = detections.confidence > 0.5
xyxy = detections.xyxy[mask]
polys = all_polys  # stale, first dim no longer matches
# after
mask = detections.confidence > 0.5
xyxy = detections.xyxy[mask]
polys = all_polys[mask] if all_polys.shape[0] == detections.xyxy.shape[0] else rebuild_polys(xyxy)
Defensive patterns

Strategy: validation

Validate before calling

n = xyxy.shape[0]
for key, arr in data.items():
    if isinstance(arr, np.ndarray) and arr.ndim > 1:
        assert arr.shape[0] == n, f'{key} first dim {arr.shape[0]} != {n}'

Type guard

def first_dim_matches(arr: np.ndarray, n: int) -> bool:
    return arr.ndim > 1 and arr.shape[0] == n

Try / catch

try:
    sv.Detections(xyxy=xyxy, data=data)
except ValueError as e:
    log.warning('data misaligned after filtering: %s', e); raise

Prevention

When it happens

Trigger: Passing `data={ORIENTED_BOX_COORDINATES: polys}` where `polys` has shape (5, 4, 2) but `xyxy` has 4 rows; attaching segmentation masks stacked for a different frame than the boxes; reusing a mask array after detections were filtered by NMS or confidence.

Common situations: Mixing arrays from consecutive video frames (batch processing) where box count changed between frames; slicing `xyxy` with a boolean mask but slicing `data` arrays with different indices; off-by-one from appending to one array and not the other.

Related errors


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