{"record":{"id":"bfea2c83489ea327","repo":"d2lang/d2","slug":"cannot-parse-hex-color-v","errorCode":null,"errorMessage":"cannot parse hex color %v","messagePattern":"cannot parse hex color (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/color/color.go","lineNumber":180,"sourceCode":"\n// https://github.com/go-playground/colors/blob/main/rgb.go#L89\nfunc (c *RGB) IsLight() bool {\n\tr := float64(c.Red)\n\tg := float64(c.Green)\n\tb := float64(c.Blue)\n\n\thsp := math.Sqrt(0.299*math.Pow(r, 2) + 0.587*math.Pow(g, 2) + 0.114*math.Pow(b, 2))\n\n\treturn hsp > 130\n}\n\n// https://gist.github.com/CraigChilds94/6514edbc6a2db5e434a245487c525c75\nfunc Hex2RGB(hex string) (RGB, error) {\n\tvar rgb RGB\n\tif len(hex) > 3 && hex[0] == '#' {\n\t\thex = hex[1:]\n\t} else {\n\t\treturn RGB{}, fmt.Errorf(\"cannot parse hex color %v\", hex)\n\t}\n\tvalues, err := strconv.ParseUint(hex, 16, 32)\n\tif err != nil {\n\t\treturn RGB{}, err\n\t}\n\n\trgb = RGB{\n\t\tRed:   uint8(values >> 16),\n\t\tGreen: uint8((values >> 8) & 0xFF),\n\t\tBlue:  uint8(values & 0xFF),\n\t}\n\n\treturn rgb, nil\n}\n\n// https://www.w3.org/TR/css-color-4/#svg-color\nvar namedRgbMap = map[string][]uint8{\n\t\"aliceblue\":            {240, 248, 255}, // #F0F8FF","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/lib/color/color.go#L162-L198","documentation":"Hex2RGB parses a hex color string into an RGB struct. It requires a '#' prefix and, for strings longer than 3 chars, strips it; if the string does not start with '#' (or is too short to be a valid hex literal), it returns this error instead of attempting ParseUint.","triggerScenarios":"Calling Hex2RGB with \"4A6FA5\", \"fff\", \"#\", or any string not beginning with '#' and longer than 3 characters.","commonSituations":"Colors obtained from config/user input without normalization, or strings already stripped of '#' by earlier processing.","solutions":["Prefix the string with '#' before calling Hex2RGB","Validate with a regexp like ^#[0-9a-fA-F]{3,8}$ before calling","Normalize user/config color input to canonical '#RRGGBB' form","If the '#' was stripped upstream, keep the original form for parsing"],"exampleFix":"// before\nrgb, err := color.Hex2RGB(\"4A6FA5\")\n// after\nif !strings.HasPrefix(hex, \"#\") { hex = \"#\" + hex }\nrgb, err := color.Hex2RGB(hex)","handlingStrategy":"validation","validationCode":"var hexRe = regexp.MustCompile(`^#[0-9a-fA-F]{3,8}$`)\nif !hexRe.MatchString(hex) {\n    return fmt.Errorf(\"not a # hex color: %q\", hex)\n}","typeGuard":"func isHexColor(s string) bool {\n    return len(s) > 3 && s[0] == '#' && regexp.MustCompile(`^#[0-9a-fA-F]{3,8}$`).MatchString(s)\n}","tryCatchPattern":"rgb, err := color.Hex2RGB(hex)\nif err != nil {\n    log.Printf(\"bad hex color %q: %v\", hex, err)\n    return fallbackColor\n}","preventionTips":["Normalize all color inputs to '#RRGGBB' before parsing","Keep the '#' prefix — do not strip it upstream","Regexp-validate user/config color strings before calling Hex2RGB"],"tags":["color","hex","parsing"],"backgroundTag":"invalid-color-value","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}