{"record":{"id":"ac2973c589f28ff9","repo":"d2lang/d2","slug":"invalid-color-s","errorCode":null,"errorMessage":"invalid color \"%s\"","messagePattern":"invalid color \"(.+?)\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/color/color.go","lineNumber":72,"sourceCode":"\n\t\tcase colorString[0] == 'N':\n\t\t\tswitch colorString[1] {\n\t\t\tcase '1', '2':\n\t\t\t\treturn N1, nil\n\t\t\tcase '3':\n\t\t\t\treturn N2, nil\n\t\t\tcase '4':\n\t\t\t\treturn N3, nil\n\t\t\tcase '5':\n\t\t\t\treturn N4, nil\n\t\t\tcase '6':\n\t\t\t\treturn N5, nil\n\t\t\tcase '7':\n\t\t\t\treturn N6, nil\n\t\t\t}\n\t\t}\n\n\t\treturn \"\", fmt.Errorf(\"invalid color \\\"%s\\\"\", colorString)\n\t}\n\n\treturn darkenCSS(colorString)\n}\n\nfunc darkenCSS(colorString string) (string, error) {\n\tc, err := csscolorparser.Parse(colorString)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\th, s, l := colorful.Color{R: c.R, G: c.G, B: c.B}.Hsl()\n\t// decrease luminance by 10%\n\treturn colorful.Hsl(h, s, l-.1).Clamped().Hex(), nil\n}\n\nfunc LuminanceCategory(colorString string) (string, error) {\n\t// check if colorString matches the `url('#grad-<sha1-hash>')` format\n\t// which is used to refer to a <linearGradient> or <radialGradient> element.","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/lib/color/color.go#L54-L90","documentation":"Darken reduces a color's luminance by 10%. If the input is one of d2's theme color tokens (checked via IsThemeColor, e.g. B1-B6, AA2-AA5, N1-N7), it maps through a hardcoded switch; any theme-style token not covered by that switch is rejected with this error instead of falling through to CSS parsing.","triggerScenarios":"Calling lib/color.Darken with a theme color token whose prefix/number is not in the switch (e.g. B7, AA1, N8, or a malformed token like 'X2'), or a non-theme string shorter than the checks.","commonSituations":"Typoed theme color names in diagrams/styles, new theme colors added upstream but not to Darken's switch, or users passing arbitrary color strings they assumed were theme tokens.","solutions":["Use a valid theme token: B1–B6, AA2/AA4/AA5, or N1–N7","If passing a regular color, use CSS syntax (hex, rgb(), named) so Darken routes to darkenCSS","Check IsThemeColor first and validate the token against the supported set","If you added a new theme constant, extend Darken's switch"],"exampleFix":"// before\nc, err := color.Darken(\"B9\") // invalid token\n// after\nc, err := color.Darken(\"B3\") // or color.Darken(\"#4A6FA5\")","handlingStrategy":"validation","validationCode":"var themeToken = regexp.MustCompile(`^(B[1-6]|AA[245]|N[1-7])$`)\nfunc canDarken(s string) bool {\n    if themeToken.MatchString(s) {\n        return true\n    }\n    _, err := csscolorparser.Parse(s)\n    return err == nil\n}","typeGuard":"func isThemeColor(s string) bool {\n    switch {\n    case strings.HasPrefix(s, \"B\") && len(s) == 2 && s[1] >= '1' && s[1] <= '6':\n        return true\n    case strings.HasPrefix(s, \"AA\") && (s[2] == '2' || s[2] == '4' || s[2] == '5'):\n        return true\n    case strings.HasPrefix(s, \"N\") && s[1] >= '1' && s[1] <= '7':\n        return true\n    }\n    return false\n}","tryCatchPattern":"dark, err := color.Darken(input)\nif err != nil {\n    log.Printf(\"cannot darken %q, using original: %v\", input, err)\n    dark = input\n}","preventionTips":["Validate theme tokens against the supported set (B1–B6, AA2/AA4/AA5, N1–N7)","For arbitrary colors use CSS syntax so darkenCSS handles them","If adding theme constants, extend Darken's switch in the same change"],"tags":["color","parsing","validation"],"backgroundTag":"invalid-color-value","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}