{"record":{"id":"57841bfde6422891","repo":"roboflow/supervision","slug":"detection-area-metadata-must-be-shaped-n-and-al","errorCode":null,"errorMessage":"Detection area metadata must be shaped (N,) and aligned with detections","messagePattern":"Detection area metadata must be shaped \\(N,\\) and aligned with detections","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/metrics/utils/object_size.py","lineNumber":299,"sourceCode":"    Example:\n        ```pycon\n        >>> import numpy as np\n        >>> from supervision.config import AREA_DATA_FIELD\n        >>> from supervision.detection.core import Detections\n        >>> detections = Detections(\n        ...     xyxy=np.array([[0, 0, 10, 10]], dtype=np.float32),\n        ...     data={AREA_DATA_FIELD: np.array([2500.0])},\n        ... )\n        >>> get_detection_size_category(detections)\n        array([2])\n\n        ```\n    \"\"\"\n    area_data = detections.data.get(AREA_DATA_FIELD)\n    if area_data is not None:\n        areas = np.asarray(area_data, dtype=np.float64)\n        if len(areas.shape) != 1 or len(areas) != len(detections):\n            raise ValueError(\n                \"Detection area metadata must be shaped (N,) and aligned \"\n                \"with detections\"\n            )\n        return get_area_size_category(areas)\n\n    if metric_target == MetricTarget.BOXES:\n        return get_bbox_size_category(detections.xyxy)\n    if metric_target == MetricTarget.MASKS:\n        mask = detections.mask\n        if mask is None:\n            raise ValueError(\"Detections mask is not available\")\n        return get_mask_size_category(mask)\n    if metric_target == MetricTarget.ORIENTED_BOUNDING_BOXES:\n        oriented_box_coordinates = detections.data.get(ORIENTED_BOX_COORDINATES)\n        if oriented_box_coordinates is None:\n            raise ValueError(\"Detections oriented bounding boxes are not available\")\n        return get_obb_size_category(\n            cast(","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/metrics/utils/object_size.py#L281-L317","documentation":"Raised by get_detection_size_category() when detections.data[AREA_DATA_FIELD] exists but is not a 1-D array of length N matching the number of detections. Precomputed area metadata is a fast path that skips recomputing areas from geometry, so it must align row-for-row with the Detections. A mismatch means the metadata is stale or malformed.","triggerScenarios":"Setting detections.data['detection_area'] (AREA_DATA_FIELD) to a scalar, an (N,1) array, or an array of a different length than len(detections) — e.g. after filtering detections with slicing, which keeps the original data array.","commonSituations":"Attaching areas from a previous processing stage, then filtering/subsetting detections without slicing the data dict; concatenating Detections with np.concatenate misaligned metadata; areas from a DataFrame column with extra rows.","solutions":["Re-align the metadata after filtering: data={AREA_DATA_FIELD: areas[keep_idx]}","Pass a 1-D array of exactly len(detections) values","Or drop the AREA_DATA_FIELD key entirely so size is recomputed from xyxy/mask/obb"],"exampleFix":"# before\nareas = np.array([[100.0], [2500.0]])          # (2, 1)\ndets = sv.Detections(xyxy=xyxy, data={AREA_DATA_FIELD: areas})\n\n# after\nareas = np.array([100.0, 2500.0])             # (2,)\ndets = sv.Detections(xyxy=xyxy, data={AREA_DATA_FIELD: areas})","handlingStrategy":"validation","validationCode":"from supervision.config import AREA_DATA_FIELD\n\nareas = np.asarray(detections.data[AREA_DATA_FIELD]).reshape(-1)\nassert len(areas) == len(detections), 'area metadata out of sync with detections'\ndetections.data[AREA_DATA_FIELD] = areas","typeGuard":"import numpy as np\n\ndef areas_aligned(dets: sv.Detections, areas: np.ndarray) -> bool:\n    \"\"\"True when areas is 1-D with one value per detection.\"\"\"\n    a = np.asarray(areas)\n    return a.ndim == 1 and len(a) == len(dets)","tryCatchPattern":"try:\n    cats = get_detection_size_category(detections, metric_target)\nexcept ValueError as e:\n    if 'aligned' in str(e):\n        detections.data.pop(AREA_DATA_FIELD, None)  # recompute from geometry\n        cats = get_detection_size_category(detections, metric_target)\n    else:\n        raise","preventionTips":["After filtering Detections, re-slice every entry in data dict with the same index array","Treat precomputed area metadata as derived state: regenerate it whenever detections change"],"tags":["metrics","object-size","data-alignment","validation"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}