junegunn/fzf · error
%s: %s
Error message
%s: %s
What it means
The file referenced by $FZF_DEFAULT_OPTS_FILE was read successfully, but its contents could not be split into shell words. fzf uses a shell-like tokenizer (parseShellWords) that understands quoting, so unterminated quotes or malformed escapes make word splitting fail. The error message includes the file path and the tokenizer's reason.
Solutions
- Open the file and run a quick balance check: grep -c "'" and grep -c '\"' to spot odd quote counts
- Fix or remove the malformed line; prefer double quotes around embedded single quotes
- Validate the file in a subshell before relying on it: eval "set -- $(cat "$FZF_DEFAULT_OPTS_FILE")" and see if the shell also complains
Example fix
# before ($FZF_DEFAULT_OPTS_FILE contents)
--preview 'cat {}
# after
--preview 'cat {}' Defensive patterns
Strategy: validation
Validate before calling
# fail fast on unbalanced quotes before running fzf
f="$FZF_DEFAULT_OPTS_FILE"
if [ -n "$f" ]; then
sq=$(tr -cd "'" < "$f" | wc -c); dq=$(tr -cd '\"' < "$f" | wc -c)
[ $((sq % 2)) -eq 0 ] && [ $((dq % 2)) -eq 0 ] || { echo 'unbalanced quotes in opts file' >&2; exit 1; }
fi Prevention
- Keep one option per line in the file so a bad line is easy to spot
- Lint the file through your shell's parser: bash -n <(cat "$FZF_DEFAULT_OPTS_FILE") as a smoke test
When it happens
Trigger: The options file contains an unbalanced quote (e.g. --preview 'cat {} without a closing quote) or an invalid escape sequence, so parseShellWords returns an error before any option is parsed.
Common situations: Hand-edited options files where a quote was accidentally deleted; embedding a preview command with nested quotes that ends up unbalanced; copying shell snippets into the file while dropping the closing quote.
Related errors
- bind action not specified
- $FZF_DEFAULT_OPTS_FILE
- $FZF_DEFAULT_OPTS
- invalid
- invalid preview window option
AI-assisted analysis of junegunn/fzf@bd4efa277b (2026-08-15).
Data as JSON: /api/errors/37651a2bd970e30c.
Report an issue: GitHub.
Appendix: source
Thrown at src/options.go:3919
return parser.Parse(str)
}
// ParseOptions parses command-line options
func ParseOptions(useDefaults bool, args []string) (*Options, error) {
opts := defaultOptions()
index := 0
if useDefaults {
// 1. Options from $FZF_DEFAULT_OPTS_FILE
if path := os.Getenv("FZF_DEFAULT_OPTS_FILE"); path != "" {
bytes, err := os.ReadFile(path)
if err != nil {
return nil, errors.New("$FZF_DEFAULT_OPTS_FILE: " + err.Error())
}
words, parseErr := parseShellWords(string(bytes))
if parseErr != nil {
return nil, errors.New(path + ": " + parseErr.Error())
}
if len(words) > 0 {
if err := parseOptions(&index, opts, words); err != nil {
return nil, errors.New(path + ": " + err.Error())
}
}
}
// 2. Options from $FZF_DEFAULT_OPTS string
words, parseErr := parseShellWords(os.Getenv("FZF_DEFAULT_OPTS"))
if parseErr != nil {
return nil, errors.New("$FZF_DEFAULT_OPTS: " + parseErr.Error())
}
if len(words) > 0 {
if err := parseOptions(&index, opts, words); err != nil {
return nil, errors.New("$FZF_DEFAULT_OPTS: " + err.Error())
}
}View on GitHub (pinned to bd4efa277b)