Textualize/rich · error · ColorParseError
expected three components in {original_color!r}
Error message
expected three components in {original_color!r} What it means
In the rgb(...) branch of Color.parse, the comma-separated payload must yield exactly three components (red, green, blue); otherwise ColorParseError("expected three components in ...") is raised. The regex accepts a fairly loose "r,g,b" payload, so 1, 2, or 4+ components reach this check and fail there rather than in the regex.
Source
Thrown at rich/color.py:473
triplet = ColorTriplet(
int(color_24[0:2], 16), int(color_24[2:4], 16), int(color_24[4:6], 16)
)
return cls(color, ColorType.TRUECOLOR, triplet=triplet)
elif color_8:
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:View on GitHub (pinned to 9d8f9a372c)
Solutions
- Supply exactly three comma-separated integers: rgb(red,green,blue)
- Strip alpha before passing: convert rgba(r,g,b,a) to rgb(r,g,b)
- Build the string from a fixed 3-tuple: f"rgb({r},{g},{b})"
Example fix
// before (Python)
Color.parse("rgb(255,0,0,0.5)") # ColorParseError: 4 components
// after
Color.parse("rgb(255,0,0)") Defensive patterns
Strategy: validation
Validate before calling
parts = rgba_string.split(",")
if len(parts) == 4:
parts = parts[:3] # drop alpha
assert len(parts) == 3, f"need r,g,b, got {parts!r}"
color_str = f"rgb({','.join(parts)})" Type guard
def is_three_component_rgb(s: str) -> bool:
parts = s.strip().removeprefix("rgb").strip("() ").split(",")
return len(parts) == 3 and all(p.strip().isdigit() for p in parts) Prevention
- Strip alpha from rgba() values before passing to rich
- Build rgb strings from a fixed 3-tuple instead of string concatenation
- Remember rich Color has no alpha channel
When it happens
Trigger: Color.parse("rgb(1,2)") (missing blue); "rgb(1,2,3,4)" (four values, e.g. an RGBA string fed in verbatim); "rgb(1,,3)" (empty component); concatenating channels with the wrong separator count.
Common situations: Feeding CSS rgba() strings into rich (rich has no alpha in Color); building rgb strings by string formatting with an accidental extra/missing comma; copy-pasting colors from design tools that emit rgba or 4-component values.
Related errors
- {original_color!r} is not a valid color
- color components must be <= 255 in {original_color!r}
- color number must be <= 255 in {color!r}
- 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/451ca48985455ca0.
Report an issue: GitHub.