roboflow/supervision · error · ValueError
COCO RLE counts cannot be empty.
Error message
COCO RLE counts cannot be empty.
What it means
Raised when the COCO RLE counts array parsed for CompactMask.from_coco_rle is empty (size 0). An RLE must contain at least one run count to describe a mask, and the code uses counts to verify total area, so an empty array is meaningless and rejected. This check runs after the one-dimensionality check.
Source
Thrown at src/supervision/detection/compact_mask.py:411
else:
# Convert to int64 first, then range-check against int32 bounds before
# narrowing. A direct int32 cast wraps silently on some numpy versions
# and raises on others; this makes overflow detection deterministic.
counts_arr64 = np.asarray(counts, dtype=np.int64)
int32_info = np.iinfo(np.int32)
if counts_arr64.size and (
counts_arr64.max() > int32_info.max
or counts_arr64.min() < int32_info.min
):
raise ValueError("COCO RLE counts exceed int32 range.")
counts_arr = counts_arr64.astype(np.int32)
except (TypeError, ValueError, OverflowError) as exc:
raise ValueError("Invalid COCO RLE counts.") from exc
if counts_arr.ndim != 1:
raise ValueError("COCO RLE counts must be one-dimensional.")
if counts_arr.size == 0:
raise ValueError("COCO RLE counts cannot be empty.")
if np.any(counts_arr < 0):
raise ValueError("COCO RLE counts must be non-negative.")
return counts_arr
def _rle_resize(
rle: npt.NDArray[np.int32],
crop_h: int,
crop_w: int,
new_crop_h: int,
new_crop_w: int,
) -> npt.NDArray[np.int32]:
"""Resize an F-order RLE-encoded crop via nearest-neighbour resampling.
Manipulates run lengths directly without decoding to a full 2D boolean
array. Delegates to :func:`_rle_split_cols`, :func:`_rle_scale_col`,
and :func:`_rle_join_cols`.
View on GitHub (pinned to 7f254d9784)
Solutions
- If the annotation genuinely has no mask, skip it instead of passing an empty RLE — filter annotations where not ann.get('segmentation').
- If a mask exists, generate a correct RLE with pycocotools.mask.encode on the binary mask so counts is populated.
- Check the JSON source for truncation if counts should not be empty.
Example fix
# before
rles = [{"size": [4, 4], "counts": []}]
# after (skip empty masks)
rles = [r for r in coco_rles if len(r["counts"]) > 0] Defensive patterns
Strategy: validation
Validate before calling
rles = [r for r in rles if len(r.get("counts", [])) > 0]
# or for compressed payloads: if r.get("counts")] Type guard
def has_nonempty_counts(rle) -> bool:
c = rle.get("counts")
return bool(c) and (not isinstance(c, (list, tuple)) or len(c) > 0) Try / catch
try:
cm = sv.CompactMask.from_coco_rle(rles, xyxy, image_shape=shape)
except ValueError as e:
if "cannot be empty" in str(e):
rles = [r for r in rles if r["counts"]]
cm = sv.CompactMask.from_coco_rle(rles, xyxy, image_shape=shape)
else:
raise Prevention
- Treat empty segmentation as 'no mask' and filter such annotations before building the RLE list.
- When serializing masks, skip zero-area masks instead of emitting empty counts.
- Keep rles and xyxy filtered in the same comprehension so indexes stay aligned.
When it happens
Trigger: Passing rle['counts'] = [] or an empty numpy array to CompactMask.from_coco_rle; or a COCO annotation whose segmentation counts field is an empty list/string.
Common situations: Placeholder annotations created for empty masks (COCO uses iscrowd/empty segmentation for no mask); truncated JSON; a serializer that dropped the counts field content; building RLEs programmatically and forgetting to fill counts.
Related errors
- COCO RLE counts must be one-dimensional.
- COCO RLE counts must be non-negative.
- Invalid COCO RLE counts.
- image_shape must contain positive height and width.
- The sum of COCO RLE counts must match the image area.
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/2b497099565ec9ba.
Report an issue: GitHub.