roboflow/supervision · error · ValueError
Value for key '{key}' must be a list or np.ndarray
Error message
Value for key '{key}' must be a list or np.ndarray What it means
Raised by supervision.validators._validate_data when a value in the Detections.data dict is neither a list nor an np.ndarray. data entries are per-detection columns; scalars, dicts, strings-as-scalar, or tensors are rejected because they cannot be aligned with xyxy.
Source
Thrown at src/supervision/validators/__init__.py:204
)
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))
if not isinstance(xy, np.ndarray) or xy.ndim != 3 or xy.shape[2] not in (2, 3):
raise ValueError(
f"xy must be a 3D np.ndarray with shape {expected_shape}, but got shape "View on GitHub (pinned to 7f254d9784)
Solutions
- Broadcast scalars: data={"score": np.full(n, 0.9)}.
- Convert tensors: tensor.detach().cpu().numpy().
- Keep frame-level metadata outside Detections (e.g. pass alongside in your own struct); data is per-detection only.
- Use recognized keys from supervision.config (e.g. CLASS_NAME_DATA_FIELD) with per-detection arrays.
Example fix
# before
dets = Detections(xyxy=boxes, data={"frame_idx": 42}) # scalar -> ValueError
# after
frame_idx = 42 # keep frame-level info outside Detections
dets = Detections(xyxy=boxes, data={"conf": np.full(len(boxes), 0.9)}) Defensive patterns
Strategy: validation
Validate before calling
n = len(xyxy)
data = {
k: (v if isinstance(v, (list, np.ndarray)) else np.full(n, v))
for k, v in data.items()
}
dets = Detections(xyxy=xyxy, data=data) Type guard
def data_values_are_columns(data: dict[str, Any]) -> bool:
return all(isinstance(v, (list, np.ndarray)) for v in data.values()) Prevention
- Remember Detections.data is per-detection columns only.
- Keep frame-level metadata outside the Detections object.
- Convert tensors to np.ndarray before storing them in data.
When it happens
Trigger: Passing data={"score": 0.9} (a bare float), data={"meta": {"frame": 1}} (a dict), or a Torch tensor as a data value when constructing Detections.
Common situations: Trying to attach global/frame-level metadata to Detections (data is per-detection only); passing model tensors without .cpu().numpy(); storing a single class name string instead of a per-detection list.
Related errors
- All data values within a single object must have equal lengt
- Length of list for key '{key}' must be {n}
- Detections must have class_id attribute.
- Both Detections should have exactly 1 detected object.
- Value must be a np.ndarray or a list
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/5700ac7bba7f7f6f.
Report an issue: GitHub.