{"record":{"id":"0a27b6fd0391581f","repo":"junegunn/fzf","slug":"key-name-required","errorCode":null,"errorMessage":"key name required","messagePattern":"key name required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/options.go","lineNumber":2028,"sourceCode":"\t\t\t}\n\t\t}\n\t\tprevSpec = \"\"\n\t}\n\treturn actions, nil\n}\n\nfunc parseKeymap(keymap map[tui.Event][]*action, str string) error {\n\tvar err error\n\tmasked := maskActionContents(str)\n\tidx := 0\n\tkeys := []string{}\n\tfor _, pairStr := range strings.Split(masked, \",\") {\n\t\torigPairStr := str[idx : idx+len(pairStr)]\n\t\tidx += len(pairStr) + 1\n\n\t\tpair := strings.SplitN(pairStr, \":\", 2)\n\t\tif len(pair[0]) == 0 {\n\t\t\treturn errors.New(\"key name required\")\n\t\t}\n\t\tkeys = append(keys, pair[0])\n\t\tif len(pair) < 2 {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, keyName := range keys {\n\t\t\tvar key tui.Event\n\t\t\tif len(keyName) == 1 && keyName[0] == escapedColon {\n\t\t\t\tkey = tui.Key(':')\n\t\t\t} else if len(keyName) == 1 && keyName[0] == escapedComma {\n\t\t\t\tkey = tui.Key(',')\n\t\t\t} else if len(keyName) == 1 && keyName[0] == escapedPlus {\n\t\t\t\tkey = tui.Key('+')\n\t\t\t} else {\n\t\t\t\tkeys, _, err := parseKeyChords(keyName, \"key name required\")\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}","sourceCodeStart":2010,"sourceCodeEnd":2046,"githubUrl":"https://github.com/junegunn/fzf/blob/bd4efa277b49ef34ca4025bff9b1a288e1980eff/src/options.go#L2010-L2046","documentation":"Thrown by parseKeymap while parsing --bind. Each comma-separated pair must be 'key:action'; a pair whose key part (before the colon) is empty — e.g. a leading or doubled comma — fails this check. The message is also reused by parseKeyChords callers like --bind-toggle-sort.","triggerScenarios":"`--bind ',ctrl-f:refresh'` (leading comma), `--bind 'ctrl-a:accept,,ctrl-b:cancel'` (doubled comma), or `--bind ':accept'` (empty key). Also from parseToggleSort when the --bind-toggle-sort key string is empty.","commonSituations":"Programmatically building bind strings and joining with commas even when one entry is empty; trailing comma left by a shell variable that expands to nothing: `--bind \"ctrl-a:accept,$EXTRA_BIND\"` with EXTRA_BIND unset.","solutions":["Inspect the --bind string for leading/trailing/doubled commas and remove them","When composing bind lists in scripts, filter out empty entries before joining","Quote shell variables and provide defaults so empty fragments never reach --bind"],"exampleFix":"# before\nEXTRA=\"\"\nfzf --bind \"ctrl-a:accept,$EXTRA\"\n# after\nBINDS=\"ctrl-a:accept${EXTRA:+,$EXTRA}\"\nfzf --bind \"$BINDS\"","handlingStrategy":"validation","validationCode":"# bash: reject empty key segments before passing to --bind\nbind_clean() {\n  printf '%s' \"$1\" | awk -F, 'BEGIN{ok=1} {for(i=1;i<=NF;i++) if ($i ~ /^([^:]*):.+/) continue; else if ($i==\"\") continue; else ok=0} END{exit !ok}'\n}\n# simpler: drop empty fragments when composing\nIFS=',' read -ra PARTS <<< \"$BINDS\"\nFILTERED=$(printf '%s' \"${PARTS[@]}\" | grep -v '^$')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use ${VAR:+,$VAR} expansion when appending optional bind fragments","Never leave bare leading/trailing commas in composed --bind strings"],"tags":["fzf","go","cli","keybinding","parsing"],"backgroundTag":null,"analyzedSha":"bd4efa277b49ef34ca4025bff9b1a288e1980eff","analyzedAt":"2026-08-15T06:11:46.983Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}