{"record":{"id":"0eb11f713c923751","repo":"roboflow/supervision","slug":"coco-rle-counts-must-be-one-dimensional","errorCode":null,"errorMessage":"COCO RLE counts must be one-dimensional.","messagePattern":"COCO RLE counts must be one-dimensional\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/compact_mask.py","lineNumber":409,"sourceCode":"            decoded_counts = _delta_decode(_base48_decode(counts))\n            counts_arr = np.array(decoded_counts, dtype=np.int32)\n        else:\n            # Convert to int64 first, then range-check against int32 bounds before\n            # narrowing. A direct int32 cast wraps silently on some numpy versions\n            # and raises on others; this makes overflow detection deterministic.\n            counts_arr64 = np.asarray(counts, dtype=np.int64)\n            int32_info = np.iinfo(np.int32)\n            if counts_arr64.size and (\n                counts_arr64.max() > int32_info.max\n                or counts_arr64.min() < int32_info.min\n            ):\n                raise ValueError(\"COCO RLE counts exceed int32 range.\")\n            counts_arr = counts_arr64.astype(np.int32)\n    except (TypeError, ValueError, OverflowError) as exc:\n        raise ValueError(\"Invalid COCO RLE counts.\") from exc\n\n    if counts_arr.ndim != 1:\n        raise ValueError(\"COCO RLE counts must be one-dimensional.\")\n    if counts_arr.size == 0:\n        raise ValueError(\"COCO RLE counts cannot be empty.\")\n    if np.any(counts_arr < 0):\n        raise ValueError(\"COCO RLE counts must be non-negative.\")\n    return counts_arr\n\n\ndef _rle_resize(\n    rle: npt.NDArray[np.int32],\n    crop_h: int,\n    crop_w: int,\n    new_crop_h: int,\n    new_crop_w: int,\n) -> npt.NDArray[np.int32]:\n    \"\"\"Resize an F-order RLE-encoded crop via nearest-neighbour resampling.\n\n    Manipulates run lengths directly without decoding to a full 2D boolean\n    array.  Delegates to :func:`_rle_split_cols`, :func:`_rle_scale_col`,","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/compact_mask.py#L391-L427","documentation":"Raised while parsing COCO RLE (Run-Length Encoding) mask counts inside CompactMask.from_coco_rle. After converting the counts payload to an int32 NumPy array, the code requires it to be strictly one-dimensional. A 2-D counts array (e.g. a list of lists) cannot represent the alternating run lengths of an RLE stream, so it is rejected before decoding.","triggerScenarios":"Calling CompactMask.from_coco_rle (directly or via a COCO dataset loader) with rle['counts'] shaped like [[0,2,2],[2,10]] or np.array([[...]]) — any nested/2-D structure instead of a flat sequence of integers.","commonSituations":"Hand-built RLE payloads where counts was accidentally wrapped in an extra list; JSON produced by a custom encoder that nested the counts; passing a decoded-then-reshaped array; mixing up the COCO compressed-string counts with a wrongly deserialized list of lists.","solutions":["Inspect the counts payload you pass and flatten it to a 1-D sequence: np.asarray(counts).reshape(-1) or [c for run in counts for c in run] only if nesting was accidental.","If counts came from pycocotools, use the uncompressed form (list of ints) or decode the compressed ASCII string first instead of wrapping it.","Verify with np.asarray(rle['counts']).ndim == 1 before calling from_coco_rle."],"exampleFix":"# before\nrles = [{\"size\": [4, 4], \"counts\": [[0, 2, 2, 2, 10]]}]\n\n# after\nrles = [{\"size\": [4, 4], \"counts\": [0, 2, 2, 2, 10]}]","handlingStrategy":"validation","validationCode":"import numpy as np\n\ndef rle_counts_ok(counts) -> bool:\n    try:\n        arr = np.asarray(counts, dtype=np.int64)\n    except (TypeError, ValueError, OverflowError):\n        return False\n    return arr.ndim == 1 and arr.size > 0 and (arr >= 0).all()","typeGuard":"def is_flat_int_sequence(counts) -> bool:\n    return isinstance(counts, (list, tuple)) and all(\n        isinstance(c, int) and not isinstance(c, bool) for c in counts\n    )","tryCatchPattern":"try:\n    cm = sv.CompactMask.from_coco_rle(rles, xyxy, image_shape=shape)\nexcept ValueError as e:\n    if \"one-dimensional\" in str(e):\n        counts = np.asarray(rle[\"counts\"]).reshape(-1).tolist()  # only if nesting was accidental\n    else:\n        raise","preventionTips":["Always produce counts as a flat list of Python ints (pycocotools.encode output is the reference).","Add a payload unit test asserting np.asarray(counts).ndim == 1 for every RLE you emit.","Never wrap counts in an extra list when building dicts programmatically."],"tags":["coco","rle","compact-mask","segmentation","validation"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}