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

  1. Ensure every character in the hex portion is 0-9 or a-f (after lowercasing).
  2. Remove embedded whitespace/unicode characters from the color string.
  3. 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

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


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/ff14cdf1780330df. Report an issue: GitHub.