junegunn/fzf · error

$FZF_DEFAULT_OPTS_FILE

Error message

$FZF_DEFAULT_OPTS_FILE: %s

What it means

fzf failed to read the file pointed to by the $FZF_DEFAULT_OPTS_FILE environment variable. The file is read before any other option source, so a broken path aborts startup entirely. The underlying OS error (e.g. 'no such file or directory', 'permission denied') is appended after the prefix.

Solutions

  1. Check the variable points to an existing readable file: echo $FZF_DEFAULT_OPTS_FILE && cat "$FZF_DEFAULT_OPTS_FILE"
  2. Fix the path in your shell rc file, or unset the variable if the file is no longer needed
  3. Verify permissions: the file must be readable by the user running fzf (chmod u+r)

Example fix

# before
export FZF_DEFAULT_OPTS_FILE=~/.config/fzf/opts   # wrong path
# after
export FZF_DEFAULT_OPTS_FILE="$HOME/.config/fzf/opts"
# or remove it if unused
unset FZF_DEFAULT_OPTS_FILE
Defensive patterns

Strategy: validation

Validate before calling

# before starting fzf
if [ -n "$FZF_DEFAULT_OPTS_FILE" ] && [ ! -r "$FZF_DEFAULT_OPTS_FILE" ]; then
  echo "FZF_DEFAULT_OPTS_FILE unreadable: $FZF_DEFAULT_OPTS_FILE" >&2
  unset FZF_DEFAULT_OPTS_FILE
fi
fzf

Prevention

When it happens

Trigger: ParseOptions(useDefaults=true, args) is called (normal fzf startup) and $FZF_DEFAULT_OPTS_FILE is set to a path that os.ReadFile cannot read: missing file, dangling symlink, directory, or unreadable permissions.

Common situations: Shell rc files exporting a stale path after the file was moved or deleted; typos in the export line; pointing at a file on an unmounted volume; CI containers where the dotfile was never copied in.

Related errors


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

Appendix: source

Thrown at src/options.go:3914

}

func parseShellWords(str string) ([]string, error) {
	parser := shellwords.NewParser()
	parser.ParseComment = true
	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())
		}

View on GitHub (pinned to bd4efa277b)