roboflow/supervision · error · TypeError
Value must be a np.ndarray or a list
Error message
Value must be a np.ndarray or a list
What it means
F1Score's kernel computes F1 = 2TP / (2TP + FP + FN) from an array whose last axis must be exactly 3 (TP, FP, FN). The guard rejects arrays whose final dimension differs — e.g. square class-confusion matrices or two-column tallies — protecting the arithmetic from silently wrong indexing.
Source
Thrown at src/supervision/key_points/core.py:1139
from supervision import _cv2 as cv2
import supervision as sv
from ultralytics import YOLO
image = cv2.imread("<SOURCE_IMAGE_PATH>")
model = YOLO('yolov8s.pt')
result = model(image)[0]
key_points = sv.KeyPoints.from_ultralytics(result)
key_points['class_name'] = [
model.model.names[class_id]
for class_id
in key_points.class_id
]
```
"""
if not isinstance(value, (np.ndarray, list)):
raise TypeError("Value must be a np.ndarray or a list")
if isinstance(value, list):
value = np.array(value)
self.data[key] = value
@classmethod
def empty(cls) -> KeyPoints:
"""
Create an empty KeyPoints object with no key points.
Returns:
An empty `sv.KeyPoints` object.
Examples:
```pycon
>>> import supervision as sv
>>> key_points = sv.KeyPoints.empty()View on GitHub (pinned to 7f254d9784)
Solutions
- Build a (N, ..., 3) array: np.stack([tp, fp, fn], axis=-1)
- Derive TP/FP/FN from a square matrix first (diagonal = TP, off-diagonal column/row sums = FP/FN) if that is what you have
- Use the public sv.F1Score API instead of the internal helper
Example fix
# before f1_score(cm.matrix) # square matrix -> ValueError # after tp = np.diag(cm.matrix).astype(np.float64) fp = cm.matrix.sum(axis=0) - tp fn = cm.matrix.sum(axis=1) - tp f1_score(np.stack([tp, fp, fn], axis=-1)) # (num_classes, 3)
Defensive patterns
Strategy: validation
Validate before calling
def to_stats(tp, fp, fn) -> np.ndarray:
tp, fp, fn = (np.asarray(x, dtype=np.float64) for x in (tp, fp, fn))
assert tp.shape == fp.shape == fn.shape
return np.stack([tp, fp, fn], axis=-1) # (..., 3)
assert to_stats(tp, fp, fn).shape[-1] == 3 Type guard
def is_tpfpfn_array(arr: np.ndarray) -> bool:
"""True when the last axis holds exactly [TP, FP, FN]."""
return isinstance(arr, np.ndarray) and arr.ndim >= 1 and arr.shape[-1] == 3 Prevention
- Convert square confusion matrices to per-class TP/FP/FN before calling F1 helpers
- Use the public sv.F1Score API which builds the 3-column stats itself
When it happens
Trigger: Passing a sv.ConfusionMatrix's (num_classes+1, num_classes+1) matrix, or a hand-built [TP, FP] array, to the module-level f1_score helper. Normally unreachable through sv.F1Score's public API, which constructs the 3-column stats itself.
Common situations: Importing internal helpers to compute F1 from a stored confusion matrix; misunderstanding that 'confusion matrix' here denotes the per-item TP/FP/FN tally.
Related errors
- Confusion matrix must have shape (..., 3), got {confusion_ma
- 2D boolean mask row count {mask.shape[0]} does not match obj
- 2D boolean mask column count {mask.shape[1]} does not match
- Cannot filter keypoints with a 2D boolean mask where rows ha
- All KeyPoints must have the same number of keypoints per ske
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/9c9992acc9c26607.
Report an issue: GitHub.