fatedier/frp · error
listen local udp addr error: %v
Error message
listen local udp addr error: %v
What it means
Returned by nathole.Prepare (pkg/nathole/nathole.go) when net.ListenUDP("udp4", laddr) fails. After resolving the local udp4 address, Prepare must actually bind a UDP socket on it for hole punching; the bind fails when the port is already taken, the address is not local, or the process lacks permission.
Source
Thrown at pkg/nathole/nathole.go:140
return nil, fmt.Errorf("discover error: %v", err)
}
if len(addrs) < 2 {
return nil, fmt.Errorf("discover error: not enough addresses")
}
localIPs, _ := ListLocalIPsForNatHole(10)
natFeature, err := ClassifyNATFeature(addrs, localIPs)
if err != nil {
return nil, fmt.Errorf("classify nat feature error: %v", err)
}
laddr, err := net.ResolveUDPAddr("udp4", localAddr.String())
if err != nil {
return nil, fmt.Errorf("resolve local udp addr error: %v", err)
}
listenConn, err := net.ListenUDP("udp4", laddr)
if err != nil {
return nil, fmt.Errorf("listen local udp addr error: %v", err)
}
// Apply NAT traversal options
var assistedAddrs []string
if !opts.DisableAssistedAddrs {
assistedAddrs = make([]string, 0, len(localIPs))
for _, ip := range localIPs {
assistedAddrs = append(assistedAddrs, net.JoinHostPort(ip, strconv.Itoa(laddr.Port)))
}
}
return &PrepareResult{
Addrs: addrs,
AssistedAddrs: assistedAddrs,
ListenConn: listenConn,
NatType: natFeature.NatType,
Behavior: natFeature.Behavior,
}, nil
}View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Check the wrapped OS error: 'address already in use' means free the port or let the previous attempt close; 'cannot assign requested address' means the interface/address vanished
- Close ListenConn from prior PrepareResult before re-preparing
- Serialize xtcp preparations within one process instead of racing them
- In containers, ensure the network namespace permits UDP binds
Example fix
// before res1, _ := nathole.Prepare(servers, opts) res2, _ := nathole.Prepare(servers, opts) // may bind same local port -> fails // after res1, _ := nathole.Prepare(servers, opts) // ... use res1 ... res1.ListenConn.Close() // free the port before preparing again res2, _ := nathole.Prepare(servers, opts)
Defensive patterns
Strategy: try-catch
Try / catch
res, err := nathole.Prepare(servers, opts)
if err != nil {
if strings.Contains(err.Error(), "listen local udp addr error") {
if errors.Is(err, syscall.EADDRINUSE) {
// close prior ListenConn or wait for the port, then retry
}
}
} Prevention
- Close PrepareResult.ListenConn when done
- Do not run concurrent Prepares that can bind the same local port
- Watch for interface churn (VPN/DHCP) between discovery and bind
When it happens
Trigger: nathole.Prepare where the resolved local address:port cannot be bound — another process (or a previous, un-reaped Prepare run) already holds the port; the address no longer exists on the host (interface removed between discovery and bind); or an OS-level restriction (sandbox/container blocking bind).
Common situations: Concurrent xtcp visits on the same machine racing for the same local port; a leaked ListenConn from an earlier failed attempt; network interfaces changing (VPN up/down, DHCP renew) between discovery and listen; container security profiles denying socket creation.
Related errors
- wait response from stun server timeout
- no external address found
- get natHoleRespMsg error: %v
- discover error: %v
- resolve local udp addr error: %v
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/62fcdd81e25b148f.
Report an issue: GitHub.