{"record":{"id":"8a4a13622d075abc","repo":"kovidgoyal/kitty","slug":"length-not-a-multiple-of-3","errorCode":null,"errorMessage":"length not a multiple of 3","messagePattern":"length not a multiple of 3","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/utils/style/wrapper.go","lineNumber":152,"sourceCode":"\t\t\t}\n\t\t\tprefix = append(prefix, strconv.Itoa(number_base+num))\n\t\t} else {\n\t\t\tprefix = append(prefix, fmt.Sprintf(\"%d:5:%d\", number_base+8, num))\n\t\t}\n\t} else {\n\t\tprefix = append(prefix, fmt.Sprintf(\"%d:2:%d:%d:%d\", number_base+8, self.val.Red, self.val.Green, self.val.Blue))\n\t}\n\treturn prefix, suffix\n}\n\ntype color_value struct {\n\tis_set bool\n\tval    color_type\n}\n\nfunc parse_sharp(color string) (ans RGBA, err error) {\n\tif len(color)%3 != 0 {\n\t\treturn RGBA{}, fmt.Errorf(\"length not a multiple of 3\")\n\t}\n\tpart_size := len(color) / 3\n\tr, g, b := color[:part_size], color[part_size:2*part_size], color[part_size*2:part_size*3]\n\tif !ans.parse_rgb_strings(r, g, b) {\n\t\terr = fmt.Errorf(\"invalid rgb numbers\")\n\t}\n\treturn\n}\n\nfunc parse_rgb(color string) (ans RGBA, err error) {\n\tcolors := strings.Split(color, \"/\")\n\tif len(colors) != 3 {\n\t\treturn RGBA{}, fmt.Errorf(\"length not a multiple of 3\")\n\t}\n\tif ans.parse_rgb_strings(colors[0], colors[1], colors[2]) {\n\t\treturn\n\t}\n\terr = fmt.Errorf(\"invalid rgb numbers\")","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/tools/utils/style/wrapper.go#L134-L170","documentation":"Raised by parse_sharp in tools/utils/style/wrapper.go when parsing a #-prefixed hex color string whose remainder (after stripping '#') has a length that is not divisible by 3. The parser splits the hex digits into three equal parts for R, G and B channels, so only balanced forms like #rgb, #rrggbb, #rrrgggbbb, #rrrrggggbbbb are accepted. Any other length (e.g. 4, 5, 7 hex digits) is rejected before numeric parsing.","triggerScenarios":"Calling ParseColor (or a style helper like to_color / Set / parse_background) with a malformed hex color such as \"#ff00\" (4 digits), \"#ff000\" (5 digits) or \"#fffffff\" (7 digits). Note ParseColor lowercases and strips inline comments, but still requires the remaining hex portion after '#' to divide evenly by 3.","commonSituations":"Typos in color literals (missing or extra digit), copying 4-digit RGBA hex (#ff0f → 'ff0f' is 4 chars, invalid here since this parser has no alpha channel), or truncation of config values like \"#ff00\" instead of \"#ff0000\" in theme/settings files.","solutions":["Correct the hex color to a 3-divisible form: #rgb, #rrggbb (most common), or longer equal-part forms.","If you intended RGBA with alpha, drop the alpha component — this parser supports only R/G/B equal-length parts.","Validate user-supplied colors with a regex like ^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$ before passing them to ParseColor.","Check for stray characters or comments appended to the color string before the parse."],"exampleFix":"// before\ncol, err := style.ParseColor(\"#ff00\") // length 4, not a multiple of 3\n\n// after\ncol, err := style.ParseColor(\"#ff0000\") // 6 hex digits, valid rrggbb","handlingStrategy":"validation","validationCode":"var hexColorRe = regexp.MustCompile(`^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{9}|[0-9a-fA-F]{12})$`)\n\nfunc validHexColor(s string) bool { return hexColorRe.MatchString(strings.TrimSpace(s)) }","typeGuard":"func isHexColor(s string) bool {\n\ts = strings.TrimPrefix(strings.TrimSpace(strings.ToLower(s)), \"#\")\n\treturn len(s)%3 == 0 && len(s) > 0\n}","tryCatchPattern":null,"preventionTips":["Normalize all colors to #rrggbb before passing to ParseColor.","Reject user color input early with a regex instead of relying on ParseColor errors.","Write tests covering 3/4/5/7-digit hex inputs."],"tags":["color","hex-parse","validation","styling"],"backgroundTag":"color-parse-failed","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}