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

  1. Supply exactly three comma-separated integers: rgb(red,green,blue)
  2. Strip alpha before passing: convert rgba(r,g,b,a) to rgb(r,g,b)
  3. 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

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


AI-assisted analysis of Textualize/rich@9d8f9a372c (2026-08-15). Data as JSON: /api/errors/451ca48985455ca0. Report an issue: GitHub.