Textualize/rich · error · ColorParseError
color components must be <= 255 in {original_color!r}
Error message
color components must be <= 255 in {original_color!r} What it means
After splitting an rgb(...) color into three integers, rich verifies each channel is <= 255 and raises ColorParseError("color components must be <= 255 in ...") otherwise. The regex only requires digit groups, so out-of-range values like 300 parse as integers but fail this semantic check. Negative values cannot occur (the regex has no minus sign), so this is purely an upper-bound failure.
Source
Thrown at rich/color.py:479
number = int(color_8)
if number > 255:
raise ColorParseError(f"color number must be <= 255 in {color!r}")
return cls(
color,
type=(ColorType.STANDARD if number < 16 else ColorType.EIGHT_BIT),
number=number,
)
else: # color_rgb:
components = color_rgb.split(",")
if len(components) != 3:
raise ColorParseError(
f"expected three components in {original_color!r}"
)
red, green, blue = components
triplet = ColorTriplet(int(red), int(green), int(blue))
if not all(component <= 255 for component in triplet):
raise ColorParseError(
f"color components must be <= 255 in {original_color!r}"
)
return cls(color, ColorType.TRUECOLOR, triplet=triplet)
@lru_cache(maxsize=1024)
def get_ansi_codes(self, foreground: bool = True) -> Tuple[str, ...]:
"""Get the ANSI escape codes for this color."""
_type = self.type
if _type == ColorType.DEFAULT:
return ("39" if foreground else "49",)
elif _type == ColorType.WINDOWS:
number = self.number
assert number is not None
fore, back = (30, 40) if number < 8 else (82, 92)
return (str(fore + number if foreground else back + number),)
elif _type == ColorType.STANDARD:View on GitHub (pinned to 9d8f9a372c)
Solutions
- Clamp each channel with min(255, max(0, int(x))) before formatting the rgb string
- Fix the scaling factor (e.g. use int(pct * 255 / 100) for percentages)
- Use round() after float scaling to avoid overshoot
Example fix
// before (Python)
Color.parse(f"rgb({level*3},{0},{0})") # level=100 -> 300 -> error
// after
r = min(255, level * 3)
Color.parse(f"rgb({r},0,0)") Defensive patterns
Strategy: validation
Validate before calling
r, g, b = (min(255, max(0, int(c))) for c in (r, g, b))
color_str = f"rgb({r},{g},{b})" Type guard
def is_in_range_channel(v: int) -> bool:
return isinstance(v, int) and 0 <= v <= 255 Prevention
- Clamp every channel to 0-255 before formatting
- Use int(pct * 255 / 100) for percentage scaling and round() after float math
- Add unit tests for boundary values (0, 255, 256) in color-mapping code
When it happens
Trigger: Color.parse("rgb(300,0,0)"); scaling data to color channels with math that can exceed 255 (e.g. heat = value * 3); passing hex-derived values computed with a wrong multiplier.
Common situations: Data-visualization code mapping magnitudes to RGB without clamping; unit mistakes (percent 0-100 multiplied by 255 instead of 2.55); copy-pasted channel values above 255 from float calculations rounded up.
Related errors
- color number must be <= 255 in {color!r}
- expected three components in {original_color!r}
- {original_color!r} is not a valid color
- invalid value for align, expected "left", "center", or "righ
- invalid value for vertical, expected "top", "middle", or "bo
AI-assisted analysis of Textualize/rich@9d8f9a372c (2026-08-15).
Data as JSON: /api/errors/018c4669087bbe74.
Report an issue: GitHub.