roboflow/supervision · error · ValueError
At least one channel is required
Error message
At least one channel is required
What it means
The fallback `cv2.merge` at src/supervision/_cv2/_color.py:93 stacks a sequence of single-channel arrays along the last axis; merging an empty sequence has no defined shape/dtype, so it raises ValueError. Mirrors OpenCV's own requirement of at least one channel.
Source
Thrown at src/supervision/_cv2/_color.py:93
green = np.choose(sector_index, (x, chroma, chroma, x, zeros, zeros))
blue = np.choose(sector_index, (zeros, zeros, x, chroma, chroma, x))
bgr = np.stack((blue + match, green + match, red + match), axis=-1) * 255
return _cast_array_like_opencv(bgr, image.dtype)
def _split(image: npt.NDArray[Any]) -> tuple[npt.NDArray[Any], ...]:
"""Split an image into contiguous single-channel arrays."""
if image.ndim == 2:
return (np.ascontiguousarray(image),)
return tuple(
np.ascontiguousarray(image[..., index]) for index in range(image.shape[2])
)
def _merge(channels: Sequence[npt.NDArray[Any]]) -> npt.NDArray[Any]:
"""Merge single-channel arrays along their final axis."""
if not channels:
raise ValueError("At least one channel is required")
return np.ascontiguousarray(np.stack(channels, axis=-1))
View on GitHub (pinned to 7f254d9784)
Solutions
- Guard before merging: `if not channels: skip or raise a domain error`
- Fix the upstream filter so it always yields >= 1 channel
- Default to a concrete channel list when the dynamic selection is empty
Example fix
// before
merged = cv2.merge(selected_channels) # selected_channels may be []
// after
if not selected_channels:
raise ValueError(f'no channels selected from {source}')
merged = cv2.merge(selected_channels) Defensive patterns
Strategy: validation
Validate before calling
def merge_channels(channels):
"""Merge only a non-empty channel sequence."""
if not channels:
raise ValueError("cannot merge zero channels")
return cv2.merge(channels) Type guard
def is_mergeable(channels) -> bool:
"""cv2.merge requires at least one channel array."""
return len(channels) > 0 Prevention
- Guard dynamic channel lists for emptiness before merging
- Log the source collection size when a channel filter can produce zero results
When it happens
Trigger: Calling `cv2.merge([])` or `cv2.merge(channels)` where `channels` is an empty list/tuple — commonly when channels are produced by filtering/slicing that can return zero elements (e.g. `cv2.split(img)[::3]` style code, or a loop building channels from a zero-length iterable).
Common situations: Dynamic channel selection where the selection set is empty for some inputs; iterating over contours/masks that yield no channel arrays and forwarding the result unconditionally.
Related errors
- All KeyPoints must have the same coordinate depth per skelet
- All or none of the '{name}' fields must be None
- Class {class_name} not found in target classes. source_class
- Image paths {duplicates} are not unique across datasets.
- Both Detections should have exactly 1 detected object.
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/b8cc73d3aa3b53d5.
Report an issue: GitHub.