roboflow/supervision · error · ValueError
Edge indices must use the 1-based convention and be within t
Error message
Edge indices must use the 1-based convention and be within the available keypoint range [1, {vertex_count}], got {edge}. What it means
Raised in Color.__post_init__ when a Color dataclass is constructed directly with any channel (r, g, b, or a) outside the 0-255 byte range. supervision validates eagerly at construction time because all downstream consumers (OpenCV drawing, image compositing) require byte-sized channel values. The message includes the offending (r, g, b, a) tuple so the out-of-range channel is immediately visible.
Source
Thrown at src/supervision/key_points/annotators.py:26
from supervision import _cv2 as cv2
from supervision.detection.utils.boxes import pad_boxes, spread_out_boxes
from supervision.draw.base import ImageType
from supervision.draw.color import Color
from supervision.draw.utils import draw_rounded_rectangle
from supervision.geometry.core import Rect
from supervision.key_points.core import KeyPoints
from supervision.key_points.skeletons import SKELETONS_BY_VERTEX_COUNT
from supervision.utils.conversion import ensure_cv2_image_for_class_method
from supervision.utils.logger import _get_logger
logger = _get_logger(__name__)
def _validate_edge_indices(edge: tuple[int, int], vertex_count: int) -> tuple[int, int]:
"""Validate 1-based skeleton edges and return zero-based vertex indexes."""
vertex_a, vertex_b = edge
if not (1 <= vertex_a <= vertex_count and 1 <= vertex_b <= vertex_count):
raise ValueError(
"Edge indices must use the 1-based convention and be within the "
f"available keypoint range [1, {vertex_count}], got {edge}."
)
# Public skeleton definitions are 1-based; keypoint arrays are zero-based.
return vertex_a - 1, vertex_b - 1
class BaseKeyPointAnnotator(ABC):
@abstractmethod
def annotate(self, scene: ImageType, key_points: KeyPoints) -> ImageType:
pass
class VertexAnnotator(BaseKeyPointAnnotator):
"""
A class that specializes in drawing skeleton vertices on images. It uses
specified key points to determine the locations where the vertices should be
drawn.View on GitHub (pinned to 7f254d9784)
Solutions
- Clamp every channel to 0-255 before constructing, e.g. sv.Color(max(0, min(255, r)), ...).
- If your source values are 0-1 floats, convert with int(round(v * 255)) first.
- Prefer the classmethods from_rgb_tuple / from_bgr_tuple / from_rgba_tuple / from_bgra_tuple or from_hex, which validate per format and document expected ranges.
- Audit any code that adds/multiplies channel values (fade-in effects, mixing) and add a clamp helper at the boundary.
Example fix
# before brightened = sv.Color(base.r + 60, base.g + 60, base.b + 60) # may exceed 255 # after clamp = lambda v: max(0, min(255, v)) brightened = sv.Color(clamp(base.r + 60), clamp(base.g + 60), clamp(base.b + 60))
Defensive patterns
Strategy: validation
Validate before calling
def clamp_channel(v: float) -> int:
"""Force any channel value into the 0-255 byte range Color requires."""
return max(0, min(255, int(round(v))))
# before: sv.Color(r + 40, g + 40, b + 40)
# after: sv.Color(clamp_channel(r + 40), clamp_channel(g + 40), clamp_channel(b + 40)) Type guard
def is_byte_color(r: float, g: float, b: float, a: float = 255) -> bool:
"""True if all channels are ints within 0-255, safe for sv.Color()."""
return all(isinstance(v, int) and 0 <= v <= 255 for v in (r, g, b, a)) Prevention
- Route all dynamic color creation through a single clamping helper instead of constructing sv.Color inline.
- Never feed 0-1 float or 16-bit channel values directly; convert ranges explicitly at the boundary.
- Use the from_*_tuple classmethods so format-specific validation and clearer messages apply.
When it happens
Trigger: Direct construction such as sv.Color(r=300, g=0, b=0), sv.Color(-1, 0, 0), or sv.Color(256, 256, 256, 300); arithmetic on colors without clamping, e.g. brightening via sv.Color(c.r + 50, c.g + 50, c.b + 50); passing floats or channel values from a library that uses 0-1 or 0-65535 ranges.
Common situations: Dynamic color math (tints, gradients, heatmaps) that overflows the byte range; migrating code from libraries with different color ranges (PIL RGB floats, CSS percentages, 16-bit image pipelines); reading channel values from external config or data files without bounds checking.
Related errors
- sigma must contain at least one value
- All sigma values must be positive
- max_axis must be positive when provided
- color length ({len(color_seq)}) must match sigma length ({le
- module {__name__} has no attribute {name}
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/9cbbba352417f618.
Report an issue: GitHub.