junegunn/fzf · error

unsupported key: ${key}

Error message

unsupported key: ${key}

What it means

The last fallback in parseKeyChords: a comma-separated key list for --bind, --expect, --multi-bind etc. tokenizes each name into alt- combos, F1–F9 single-char forms, and single runes. Any token that is none of those — a multi-character name the switch above did not recognize — falls through to 'unsupported key: <key>'.

Source

Thrown at src/options.go:1314

				switch r {
				case escapedColon:
					r = ':'
				case escapedComma:
					r = ','
				case escapedPlus:
					r = '+'
				}
				evt := tui.AltKey(r)
				chords[evt] = key
				list = append(list, evt)
			} else if len(key) == 2 && strings.HasPrefix(lkey, "f") && key[1] >= '1' && key[1] <= '9' {
				add(tui.EventType(tui.F1.Int() + int(key[1]) - '1'))
			} else if len(runes) == 1 {
				evt := tui.Key(runes[0])
				chords[evt] = key
				list = append(list, evt)
			} else {
				return nil, list, errors.New("unsupported key: " + key)
			}
		}
	}
	return chords, list, nil
}

func parseEveryEvent(arg string) (tui.Event, error) {
	secs, err := strconv.ParseFloat(strings.TrimSpace(arg), 64)
	if err != nil || math.IsNaN(secs) || math.IsInf(secs, 0) || secs <= 0 {
		return tui.Event{}, errors.New("every() requires a positive number of seconds")
	}
	if secs < 0.01 {
		secs = 0.01
	}
	ms := math.Round(secs * 1000)
	if ms > math.MaxInt32 {
		return tui.Event{}, errors.New("every() interval is too large")
	}

View on GitHub (pinned to bd4efa277b)

Solutions

  1. Consult fzf --help for the exact key names (ctrl-*, alt-*, f1-f12, shift-up/down, btab, tab, enter, space, bs, del, home, end, pgup, pgdn, up, down, left, right)
  2. Fix spelling: 'btab' not 'shift-tab', 'alt-z' not 'altz'
  3. Remove stray whitespace and empty tokens between commas
  4. Upgrade fzf if the key was added in a newer release (e.g. focus events in 0.35+)

Example fix

# before
fzf --bind 'shift-tab:up'
# after
fzf --bind 'btab:up'
Defensive patterns

Strategy: validation

Validate before calling

KEYS='ctrl-a,btab,f3'
IFS=',' read -ra KS <<< "$KEYS"
for k in "${KS[@]}"; do
  [[ "$k" =~ ^(ctrl|alt|shift)-(a-z|0-9|f1-f12|up|down|left|right|enter|space|tab|btab|del|home|end|pgup|pgdn|bs)$ ]] || { echo "unsupported key: $k" >&2; exit 1; }
done
fzf --bind "ctrl-a:accept" --expect "$KEYS"

Type guard

isValidFzfKey() { [[ "$1" =~ ^(ctrl-|alt-|shift-)?[a-z0-9]+$ || "$1" =~ ^(f[1-9]|f1[0-2]|tab|btab|enter|space|bs|del|home|end|pgup|pgdn|up|down|left|right|left-click|right-click|scroll-up|scroll-down|double-click)$ ]]; }

Prevention

When it happens

Trigger: --bind 'ctrl-f2:...' style tokens not handled, unrecognized names like --expect 'ctrl-a,spacebar', 'home' on versions lacking it, 'shift-tab' written where 'btab' is expected, or key names with trailing whitespace from multiline --bind strings.

Common situations: Bind scripts targeting newer/older fzf key vocabularies (e.g. 'pos' or 'jump' actions vs keys); copy-pasted wiki examples for a different version; Windows/macOS terminal-specific names not portable to the Linux build.

Related errors


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