kovidgoyal/kitty · error
invalid rgb numbers
Error message
invalid rgb numbers
What it means
Raised by parse_sharp after the hex string was successfully split into three equal parts, but at least one part failed to parse as a valid number via parse_rgb_strings. Each part is parsed as a hexadecimal component; non-hex characters (g-z, punctuation, spaces) cause failure. This indicates a structurally-balanced but numerically invalid hex color.
Source
Thrown at tools/utils/style/wrapper.go:157
} else {
prefix = append(prefix, fmt.Sprintf("%d:2:%d:%d:%d", number_base+8, self.val.Red, self.val.Green, self.val.Blue))
}
return prefix, suffix
}
type color_value struct {
is_set bool
val color_type
}
func parse_sharp(color string) (ans RGBA, err error) {
if len(color)%3 != 0 {
return RGBA{}, fmt.Errorf("length not a multiple of 3")
}
part_size := len(color) / 3
r, g, b := color[:part_size], color[part_size:2*part_size], color[part_size*2:part_size*3]
if !ans.parse_rgb_strings(r, g, b) {
err = fmt.Errorf("invalid rgb numbers")
}
return
}
func parse_rgb(color string) (ans RGBA, err error) {
colors := strings.Split(color, "/")
if len(colors) != 3 {
return RGBA{}, fmt.Errorf("length not a multiple of 3")
}
if ans.parse_rgb_strings(colors[0], colors[1], colors[2]) {
return
}
err = fmt.Errorf("invalid rgb numbers")
return
}
func parse_rgbi(color string) (ans RGBA, err error) {
colors := strings.Split(color, "/")View on GitHub (pinned to 6d5d0c4406)
Solutions
- Ensure every character in the hex portion is 0-9 or a-f (after lowercasing).
- Remove embedded whitespace/unicode characters from the color string.
- Pre-validate with a regex such as ^#[0-9a-fA-F]+$ (with 3-divisible length) before calling ParseColor.
Example fix
// before
col, err := style.ParseColor("#gg0000") // 'g' is not a hex digit
// after
col, err := style.ParseColor("#00gg00".ReplaceAll) // no — use:
col, err := style.ParseColor("#0f0") // valid short hex Defensive patterns
Strategy: validation
Validate before calling
func validHexDigits(s string) bool {
s = strings.TrimPrefix(strings.TrimSpace(strings.ToLower(s)), "#")
if len(s)%3 != 0 { return false }
for _, r := range s {
if !(r >= '0' && r <= '9' || r >= 'a' && r <= 'f') { return false }
}
return true
} Type guard
func isHexColor(s string) bool {
s = strings.TrimPrefix(strings.ToLower(strings.TrimSpace(s)), "#")
return len(s) > 0 && len(s)%3 == 0 && strings.Trim(s, "0123456789abcdef") == ""
} Prevention
- Strip whitespace and unicode artifacts from color strings.
- Use a strict ^#[0-9a-f]{6}$ allow-list for user input.
- Generate colors programmatically (fmt.Sprintf("#%02x%02x%02x", r, g, b)) rather than hand-typing.
When it happens
Trigger: ParseColor("#zz0000") — length 6 splits into "zz","00","00", but 'z' is not a hex digit. Also strings like "#1x2 3x4" where whitespace or invalid characters end up inside the hex components after comment stripping/lowercasing.
Common situations: Typos in hex literals (using letters beyond f), pasting colors containing whitespace or unicode look-alike characters, or config values with embedded garbage that survives the comment-stripping logic.
Related errors
- length not a multiple of 3
- not a valid color name: %#v
- not a valid color name: %#v %w
- Invalid color name: {raw!r}
- Invalid value for --background: %w
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/ff14cdf1780330df.
Report an issue: GitHub.