fatedier/frp · critical

listen on quic udp address %s error: %v

Error message

listen on quic udp address %s error: %v

What it means

When QUICBindPort > 0, frps calls quic.ListenAddr on BindAddr:QUICBindPort with the server TLS config. Any failure (bind error, TLS misconfiguration) aborts service creation with the address echoed in the error.

Source

Thrown at server/service.go:275

		address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.KCPBindPort))
		svr.kcpListener, err = netpkg.ListenKcp(address)
		if err != nil {
			return nil, fmt.Errorf("listen on kcp udp address %s error: %v", address, err)
		}
		log.Infof("frps kcp listen on udp %s", address)
	}

	if cfg.QUICBindPort > 0 {
		address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.QUICBindPort))
		quicTLSCfg := tlsConfig.Clone()
		quicTLSCfg.NextProtos = []string{"frp"}
		svr.quicListener, err = quic.ListenAddr(address, quicTLSCfg, &quic.Config{
			MaxIdleTimeout:     time.Duration(cfg.Transport.QUIC.MaxIdleTimeout) * time.Second,
			MaxIncomingStreams: int64(cfg.Transport.QUIC.MaxIncomingStreams),
			KeepAlivePeriod:    time.Duration(cfg.Transport.QUIC.KeepalivePeriod) * time.Second,
		})
		if err != nil {
			return nil, fmt.Errorf("listen on quic udp address %s error: %v", address, err)
		}
		log.Infof("frps quic listen on %s", address)
	}

	if cfg.SSHTunnelGateway.BindPort > 0 {
		sshGateway, err := ssh.NewGateway(cfg.SSHTunnelGateway, cfg.BindAddr, svr.sshTunnelListener)
		if err != nil {
			return nil, fmt.Errorf("create ssh gateway error: %v", err)
		}
		svr.sshTunnelGateway = sshGateway
		log.Infof("frps sshTunnelGateway listen on port %d", cfg.SSHTunnelGateway.BindPort)
	}

	// Listen for accepting connections from client using websocket protocol.
	websocketPrefix := []byte("GET " + netpkg.FrpWebsocketPath)
	websocketLn := svr.muxer.Listen(0, uint32(len(websocketPrefix)), func(data []byte) bool {
		return bytes.Equal(data, websocketPrefix)
	})

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Free or change quicBindPort
  2. Validate the TLS cert/key pair configured on frps (they must parse and match)
  3. Confirm UDP egress/ingress is permitted if behind NAT/firewalls
  4. Disable quicBindPort if QUIC transport is not needed
Defensive patterns

Strategy: validation

Validate before calling

// Validate TLS material and UDP port before enabling QUIC.
if _, err := tls.LoadX509KeyPair(cfg.TLSCertFile, cfg.TLSKeyFile); err != nil {
    return err
}
if c, err := net.ListenPacket("udp", addr); err != nil { return err } else { c.Close() }

Prevention

When it happens

Trigger: QUIC UDP port already in use; TLS certificate/key invalid so the cloned tlsConfig cannot back a QUIC listener; BindAddr not present on the host.

Common situations: Running QUIC on a port already used by another QUIC/HTTP3 service; self-signed or unreadable cert files; UDP blocked by cloud security groups.

Related errors


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