roboflow/supervision · error · ValueError

RGBA must be a 4-tuple with values between 0-255.

Error message

RGBA must be a 4-tuple with values between 0-255.

What it means

Raised by `supervision.annotators.utils.rgba_to_hex` when `rgba` is not a sequence of exactly 4 values or when any component is outside 0-255. The function formats each channel as two uppercase hex digits, so out-of-range or missing channels cannot be encoded.

Source

Thrown at src/supervision/annotators/utils.py:485

    Args:
        rgba: RGBA values in range 0-255.

    Returns:
        Hex color string in the format "#RRGGBBAA".

    Raises:
        ValueError: If `rgba` is not a 4-tuple or contains values outside 0-255.

    Examples:
        ```pycon
        >>> from supervision.annotators.utils import rgba_to_hex
        >>> rgba_to_hex((255, 0, 255, 128))
        '#FF00FF80'

        ```
    """
    if len(rgba) != 4 or not all(0 <= c <= 255 for c in rgba):
        raise ValueError("RGBA must be a 4-tuple with values between 0-255.")
    return "#{:02X}{:02X}{:02X}{:02X}".format(*rgba)


def is_valid_hex(hex_color: str) -> bool:
    """
    Checks if a given string is a valid hex color.

    Args:
        hex_color: A hex color string with an optional leading "#". Supports
            6-digit (RGB) or 8-digit (RGBA) formats.

    Returns:
        True if the string is a valid 6- or 8-digit hex color, otherwise False.

    Examples:
        ```pycon
        >>> from supervision.annotators.utils import is_valid_hex
        >>> is_valid_hex("#FF00FF")

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Scale normalized floats to 0-255 before calling: `tuple(int(c * 255) for c in rgba_0_1)`.
  2. Ensure exactly 4 components; append `255` if your source tuple is RGB-only.
  3. Clamp computed channels with `min(255, max(0, round(c)))` before conversion.

Example fix

# before
rgba_to_hex((1.0, 0.0, 1.0, 0.5))  # normalized floats, wrong scale

# after
rgba_to_hex((255, 0, 255, 128))  # 0-255 ints, alpha 0.5 -> 128
Defensive patterns

Strategy: validation

Validate before calling

def to_rgba255(rgba) -> tuple[int, int, int, int]:
    rgba = tuple(int(round(c * 255)) if 0 <= c <= 1.0 and isinstance(c, float) else int(c) for c in rgba)
    if len(rgba) != 4:
        raise ValueError("expected 4 components")
    return tuple(min(255, max(0, c)) for c in rgba)  # type: ignore[return-value]

Type guard

def is_valid_rgba(v) -> bool:
    return (
        isinstance(v, (tuple, list))
        and len(v) == 4
        and all(isinstance(c, (int, float)) and 0 <= c <= 255 for c in v)
    )

Prevention

When it happens

Trigger: Calling `rgba_to_hex((255, 0, 255))` (3-tuple), `rgba_to_hex((255, 0, 255, 256))`, `rgba_to_hex((255, -1, 0, 128))`, or passing float alpha as 1.0 instead of 255 (e.g. `rgba_to_hex((1.0, 0.5, 0.0, 1.0))` fails because 1.0 > 255 is false but 1.0 passes... actually 0 <= 1.0 <= 255 passes while 300 or 256 fails).

Common situations: Passing normalized 0-1 floats from matplotlib/PIL conventions where supervision expects 0-255 ints; forgetting the alpha channel when converting from an RGB tuple; off-by-one alpha computed as 256 from a percentage calculation like `int(alpha_pct * 256)`.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/cb59c3d4051cacbe. Report an issue: GitHub.