fatedier/frp · critical
create server listener error, %v
Error message
create server listener error, %v
What it means
During frps startup, when tcpmuxHTTPConnectPort > 0 the server tries to net.Listen on ProxyBindAddr:TCPMuxHTTPConnectPort. Any bind failure (port in use, permission denied, bad address) aborts service creation with this error, so frps exits before serving anything.
Source
Thrown at server/service.go:196
sshTunnelListener: netpkg.NewInternalListener(),
httpVhostRouter: vhost.NewRouters(),
auth: authRuntime,
webServer: webServer,
tlsConfig: tlsConfig,
cfg: cfg,
ctx: context.Background(),
}
if webServer != nil {
webServer.RouteRegister(svr.registerRouteHandlers)
}
// Create tcpmux httpconnect multiplexer.
if cfg.TCPMuxHTTPConnectPort > 0 {
var l net.Listener
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.TCPMuxHTTPConnectPort))
l, err = net.Listen("tcp", address)
if err != nil {
return nil, fmt.Errorf("create server listener error, %v", err)
}
svr.rc.TCPMuxHTTPConnectMuxer, err = tcpmux.NewHTTPConnectTCPMuxer(l, cfg.TCPMuxPassthrough, vhostReadWriteTimeout)
if err != nil {
return nil, fmt.Errorf("create vhost tcpMuxer error, %v", err)
}
log.Infof("tcpmux httpconnect multiplexer listen on %s, passthrough: %v", address, cfg.TCPMuxPassthrough)
}
// Init all plugins
for _, p := range cfg.HTTPPlugins {
svr.pluginManager.Register(plugin.NewHTTPPluginOptions(p))
log.Infof("plugin [%s] has been registered", p.Name)
}
svr.rc.PluginManager = svr.pluginManager
// Init group controller
svr.rc.TCPGroupCtl = group.NewTCPGroupCtl(svr.rc.TCPPortManager)View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Free the port or pick another tcpmuxHTTPConnectPort
- If binding <1024, run with adequate capability (setcap/cap_net_bind_service) or choose a high port
- Verify ProxyBindAddr is a local interface IP or 0.0.0.0
Example fix
# before tcpmuxHTTPConnectPort = 443 # permission denied as non-root # after tcpmuxHTTPConnectPort = 12443
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight the port before frps tries to bind it.
func portFree(network, addr string) bool {
l, err := net.Listen(network, addr)
if err != nil { return false }
l.Close()
return true
}
if !portFree("tcp", fmt.Sprintf("%s:%d", cfg.ProxyBindAddr, cfg.TCPMuxHTTPConnectPort)) {
return fmt.Errorf("tcpmux port %d already in use", cfg.TCPMuxHTTPConnectPort)
} Prevention
- Maintain one authoritative list of ports per host and check it in config management
- Run frps under a supervisor that surfaces startup bind failures loudly
- Avoid privileged ports unless the process has cap_net_bind_service
When it happens
Trigger: Another process already listening on the tcpmux httpconnect port; binding a privileged port (<1024) as non-root; ProxyBindAddr set to an IP not present on the machine.
Common situations: Port collision with another frps instance or service; hardened/container environments blocking low ports; typo in bind address.
Related errors
- listen on kcp udp address %s error: %v
- listen on quic udp address %s error: %v
- create vhost http listener error, %v
- login to the server failed: %v. With loginFailExit enabled,
- acquire port %d error: %v
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/cdf525980b99a849.
Report an issue: GitHub.