junegunn/fzf · error

invalid color specification: ${str}

Error message

invalid color specification: ${str}

What it means

parseTheme processes colon-separated --color arguments. Each component must be a known theme keyword (dark, light, 16, bw, ...) or a 'facet:ansi-256-color-or-#rrggbb' pair. A component that is neither — fewer than 2 parts after splitting on ':', or a facet/color pair that fails color parsing — sets this error via the fail() closure.

Source

Thrown at src/options.go:1440

			continue
		}
		switch str {
		case "dark":
			baseTheme = tui.Dark256
			theme = dupeTheme(tui.Dark256)
		case "light":
			baseTheme = tui.Light256
			theme = dupeTheme(tui.Light256)
		case "base16", "16":
			baseTheme = tui.Default16
			theme = dupeTheme(tui.Default16)
		case "bw", "no":
			baseTheme = tui.NoColorTheme
			theme = dupeTheme(tui.NoColorTheme)
		default:
			fail := func() {
				// Let the code proceed to simplify the error handling
				err = errors.New("invalid color specification: " + str)
			}
			// Color is disabled
			if theme == nil {
				continue
			}

			components := strings.Split(str, ":")
			if len(components) < 2 {
				fail()
			}

			mergeAttr := func(cattr *tui.ColorAttr) {
				for _, component := range components[1:] {
					switch component {
					case "regular":
						cattr.Attr = tui.AttrRegular
					case "bold", "strong":
						cattr.Attr |= tui.Bold

View on GitHub (pinned to bd4efa277b)

Solutions

  1. Use 'facet:value' pairs with valid colors: --color 'fg:15,bg:#1e1e2e,pointer:3'
  2. Check facet names against fzf --help (fg, bg, preview-fg, preview-bg, hl, hl+, gutter, border, prompt, pointer, marker, spinner, header, label, query, info, separator)
  3. Fix quoting so the colon-pair survives shell parsing: --color "gutter:${c:--1}"
  4. Remove empty components caused by double colons

Example fix

# before
fzf --color 'border,fg:15'
# after
fzf --color 'border:8,fg:15'
Defensive patterns

Strategy: type-guard

Validate before calling

validate_color_pair() {
  local facet color
  facet="${1%%:*}" color="${1##*:}"
  [[ "$1" == *:* ]] || return 1
  [[ "$facet" =~ ^(fg|bg|preview-fg|preview-bg|hl|hl\+|gutter|border|prompt|pointer|marker|spinner|header|label|query|info|separator|border-label)$ ]] || return 1
  [[ "$color" =~ ^(-1|[0-9]{1,3}|#[0-9a-fA-F]{6})$ ]] || return 1
}
for c in 'fg:15' 'border:#ff0000'; do validate_color_pair "$c" || { echo "bad color spec: $c" >&2; exit 1; }; done

Type guard

isValidFzfColorSpec() { [[ "$1" =~ ^(fg|bg|hl|hl\+|gutter|border|prompt|pointer|marker|spinner|header|label|query|info|separator):(-1|[0-9]{1,3}|#[0-9a-fA-F]{6})$ ]]; }

Prevention

When it happens

Trigger: --color border (missing ':value'), --color sp: (empty color), --color 'fg:#GGGGGG' (bad hex), --color pointer:pink (not a color name), stray empty components from 'a::b' style typos.

Common situations: Terminal-specific color configs ported between tools; missing value after a rename of a facet; quoting issues that swallow the ':'-half; themes written for newer fzf facets on an older binary.

Related errors


AI-assisted analysis of junegunn/fzf@bd4efa277b (2026-08-15). Data as JSON: /api/errors/ac5e12e8208452ab. Report an issue: GitHub.