junegunn/fzf · error
FZF_API_KEY is required to allow remote access
Error message
FZF_API_KEY is required to allow remote access
What it means
fzf's HTTP server (--listen) was given a non-local bind address, but no FZF_API_KEY environment variable is set. Because a remote listener lets any reachable client drive the selector, fzf refuses to start without an API key. This is a deliberate security guard, not a misconfiguration of the address itself.
Source
Thrown at src/server.go:86
return defaultListenAddr, fmt.Errorf("invalid listen address: %s", address)
}
portStr := parts[len(parts)-1]
port, err := strconv.Atoi(portStr)
if err != nil || port < 0 || port > 65535 {
return defaultListenAddr, fmt.Errorf("invalid listen port: %s", portStr)
}
if len(parts[0]) == 0 {
parts[0] = "localhost"
}
return listenAddress{parts[0], port, ""}, nil
}
func startHttpServer(address listenAddress, actionChannel chan []*action, getHandler func(getParams) string) (net.Listener, int, error) {
host := address.host
port := address.port
apiKey := os.Getenv("FZF_API_KEY")
if !address.IsLocal() && len(apiKey) == 0 {
return nil, port, errors.New("FZF_API_KEY is required to allow remote access")
}
var listener net.Listener
var err error
if len(address.sock) > 0 {
if _, err := os.Stat(address.sock); err == nil {
// Check if the socket is already in use
if conn, err := net.Dial("unix", address.sock); err == nil {
conn.Close()
return nil, 0, fmt.Errorf("socket already in use: %s", address.sock)
}
os.Remove(address.sock)
}
listener, err = net.Listen("unix", address.sock)
if err != nil {
return nil, 0, fmt.Errorf("failed to listen on %s", address.sock)
}
os.Chmod(address.sock, 0600)View on GitHub (pinned to bd4efa277b)
Solutions
- Set an API key: export FZF_API_KEY=$(head -c16 /dev/urandom | base64) before starting fzf
- Or restrict the listener to loopback if remote access is not actually needed: --listen=127.0.0.0:6266 or plain --listen
- Clients must then send the key via the X-api-key header on every request
Example fix
# before fzf --listen=0.0.0.0:6266 # after export FZF_API_KEY='s3cret-key' fzf --listen=0.0.0.0:6266 curl -H 'X-api-key: s3cret-key' http://host:6266/?q=query
Defensive patterns
Strategy: validation
Validate before calling
# guard the listener start in shell
host=0.0.0.0; port=6266
if [ "$host" != "localhost" ] && [ "$host" != "127.0.0.1" ] && [ -z "${FZF_API_KEY:-}" ]; then
echo 'refusing remote --listen without FZF_API_KEY' >&2; exit 1
fi
fzf --listen="$host:$port" Prevention
- Default to loopback listeners; widen only when remote control is truly required
- Generate the key per session and distribute it to clients over a secret store, not the command line
When it happens
Trigger: Running e.g. fzf --listen=0.0.0.0:6266 or --listen=192.168.1.5:6266 without FZF_API_KEY in the environment; only loopback hosts (localhost, 127.0.0.1, [::1]) are exempt via address.IsLocal().
Common situations: Running fzf in a container or on a server and wanting to control it from another machine; Docker port-forwarding setups where localhost inside the container is not the host's localhost.
Related errors
- permission denied: ${path}
- invalid popup option: ${arg} (expected: [center|top|bottom|l
- not a valid integer: ${str}
- invalid listen address: %s
- invalid listen port: %s
AI-assisted analysis of junegunn/fzf@bd4efa277b (2026-08-15).
Data as JSON: /api/errors/90868db6181b2dbf.
Report an issue: GitHub.