fatedier/frp · error

dial udp error: %v

Error message

dial udp error: %v

What it means

KCPTunnelSession.Init closed the discovery listen socket and failed to DialUDP a new UDP socket bound to the same local address toward the rendezvous address raddr. This is the first step of building the KCP data channel after hole punching; failing here means the OS refused to allocate the UDP socket.

Source

Thrown at client/visitor/xtcp.go:342

	Close()
}

type KCPTunnelSession struct {
	session *fmux.Session
	lConn   *net.UDPConn
	mu      sync.RWMutex
}

func NewKCPTunnelSession() TunnelSession {
	return &KCPTunnelSession{}
}

func (ks *KCPTunnelSession) Init(listenConn *net.UDPConn, raddr *net.UDPAddr) error {
	listenConn.Close()
	laddr, _ := net.ResolveUDPAddr("udp", listenConn.LocalAddr().String())
	lConn, err := net.DialUDP("udp", laddr, raddr)
	if err != nil {
		return fmt.Errorf("dial udp error: %v", err)
	}
	remote, err := netpkg.NewKCPConnFromUDP(lConn, true, raddr.String())
	if err != nil {
		lConn.Close()
		return fmt.Errorf("create kcp connection from udp connection error: %v", err)
	}

	fmuxCfg := fmux.DefaultConfig()
	fmuxCfg.KeepAliveInterval = 10 * time.Second
	fmuxCfg.MaxStreamWindowSize = 6 * 1024 * 1024
	fmuxCfg.LogOutput = io.Discard
	session, err := fmux.Client(remote, fmuxCfg)
	if err != nil {
		remote.Close()
		return fmt.Errorf("initial client session error: %v", err)
	}
	ks.mu.Lock()
	ks.session = session

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Check file descriptor limits (ulimit -n) and raise them if frpc manages many connections.
  2. Retry the visitor connection; a transient bind conflict usually clears once the old socket is reaped.
  3. If persistent, identify the failing local address (strace/lsof) and confirm the NAT mapping from the nathole exchange is still valid.
  4. Update frpc/frps; xtcp socket lifecycle improves across releases.
Defensive patterns

Strategy: retry

Prevention

When it happens

Trigger: net.DialUDP("udp", laddr, raddr) errors: local port conflict (TIME_WAIT or another socket grabbed it), UDP socket exhaustion (EMFILE), permission issues, or an invalid resolved raddr after the hole-punch exchange.

Common situations: File-descriptor limits hit by a busy frpc; the hole-punch local address became invalid because the NAT rebound the mapping; races where the listen conn's local port is reused by another visitor dialing simultaneously.

Related errors


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