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

  1. Free the port or pick another tcpmuxHTTPConnectPort
  2. If binding <1024, run with adequate capability (setcap/cap_net_bind_service) or choose a high port
  3. 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

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


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/cdf525980b99a849. Report an issue: GitHub.