wavetermdev/waveterm · error

color must start with #

Error message

color must start with #

What it means

validateHexColor rejects any color argument that doesn't begin with '#' before attempting hex decoding. `wsh setbg --border-color` (and related color flags / positional color arg) only accept either hex colors or CSS color names; a bare value like "FF0000" or "red" missing the hash goes through this branch when it doesn't match a CSS name either.

Source

Thrown at cmd/wsh/cmd/wshcmd-setbg.go:68

)

func init() {
	rootCmd.AddCommand(setBgCmd)
	setBgCmd.Flags().Float64Var(&setBgOpacity, "opacity", 0.5, "background opacity (0.0-1.0)")
	setBgCmd.Flags().BoolVar(&setBgTile, "tile", false, "tile the background image")
	setBgCmd.Flags().BoolVar(&setBgCenter, "center", false, "center the image without scaling")
	setBgCmd.Flags().StringVar(&setBgSize, "size", "auto", "size for centered images (px, %, or auto)")
	setBgCmd.Flags().BoolVar(&setBgClear, "clear", false, "clear the background")
	setBgCmd.Flags().BoolVar(&setBgPrint, "print", false, "print the metadata without applying it")
	setBgCmd.Flags().StringVar(&setBgBorderColor, "border-color", "", "block frame border color (#RRGGBB, #RRGGBBAA, or CSS color name)")
	setBgCmd.Flags().StringVar(&setBgActiveBorderColor, "active-border-color", "", "block frame focused border color (#RRGGBB, #RRGGBBAA, or CSS color name)")

	setBgCmd.MarkFlagsMutuallyExclusive("tile", "center")
}

func validateHexColor(color string) error {
	if !strings.HasPrefix(color, "#") {
		return fmt.Errorf("color must start with #")
	}
	colorHex := color[1:]
	if len(colorHex) != 6 && len(colorHex) != 8 {
		return fmt.Errorf("color must be in #RRGGBB or #RRGGBBAA format")
	}
	_, err := hex.DecodeString(colorHex)
	if err != nil {
		return fmt.Errorf("invalid hex color: %v", err)
	}
	return nil
}

func validateColor(color string) error {
	if strings.HasPrefix(color, "#") {
		return validateHexColor(color)
	}
	if !CssColorNames[strings.ToLower(color)] {
		return fmt.Errorf("invalid color %q: must be a hex color (#RRGGBB or #RRGGBBAA) or a CSS color name", color)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Prefix the value with '#': `wsh setbg --border-color #FF0000`.
  2. Quote the argument in shells that treat '#' as a comment: `wsh setbg --border-color '#FF0000'`.
  3. Or use a valid CSS color name: `wsh setbg --border-color red`.

Example fix

// before
wsh setbg --border-color FF0000
// after
wsh setbg --border-color '#FF0000'
Defensive patterns

Strategy: validation

Validate before calling

func isCssColorName(c string) bool { return CssColorNames[strings.ToLower(c)] }
func looksLikeHex(c string) bool { return strings.HasPrefix(c, "#") }
// before calling: if !looksLikeHex(v) && !isCssColorName(v) { fix arg }

Type guard

func isValidColorArg(c string) bool {
    if strings.HasPrefix(c, "#") { return len(c) == 7 || len(c) == 9 }
    return CssColorNames[strings.ToLower(c)]
}

Try / catch

if err := validateColor(v); err != nil {
    if strings.Contains(err.Error(), "must start with #") { /* suggest: append '#' or use CSS name */ }
    return err
}

Prevention

When it happens

Trigger: Calling `wsh setbg --border-color FF0000` or `wsh setbg red-ish` — a value with no leading '#' that is also not in the CssColorNames map.

Common situations: Copy-pasting a hex value without the '#'; forgetting the '#' after shell quoting; supplying an invented color name not in the CSS color list.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/fbd670eb34bed75c. Report an issue: GitHub.