fatedier/frp · error
discover error: %v
Error message
discover error: %v
What it means
Returned by nathole.Prepare (pkg/nathole/nathole.go) when Discover(stunServers, "") fails outright before any addresses are gathered. The wrapped error comes from the discovery layer — typically every STUN server timing out ('wait response from stun server timeout') or responding without a mapped address ('no external address found').
Source
Thrown at pkg/nathole/nathole.go:122
}
mm, ok := m.(*msg.NatHoleResp)
if !ok {
return fmt.Errorf("get natHoleRespMsg error: invalid message type")
}
natHoleRespMsg = mm
if natHoleRespMsg.Error != "" {
return fmt.Errorf("%s", natHoleRespMsg.Error)
}
return nil
}
// Prepare is used to do some preparation work before penetration.
func Prepare(stunServers []string, opts PrepareOptions) (*PrepareResult, error) {
// discover for Nat type
addrs, localAddr, err := Discover(stunServers, "")
if err != nil {
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)View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Check the wrapped error to distinguish timeout (blocked/dead server) from no-mapped-address (bad server)
- Verify outbound UDP to the STUN servers works from this host
- Configure multiple valid STUN servers on frps
- If UDP is blocked, hole punching is impossible — use stcp/tcp relay instead of xtcp
Defensive patterns
Strategy: fallback
Try / catch
res, err := nathole.Prepare(servers, opts)
if err != nil {
if strings.Contains(err.Error(), "discover error:") && !strings.Contains(err.Error(), "not enough addresses") {
// all STUN failed: check UDP egress; if blocked, use stcp/tcp instead of xtcp
}
} Prevention
- Pre-verify UDP/STUN reachability on hosts that will use xtcp
- Maintain a healthy STUN server list
- Have a relay (stcp) fallback ready in restricted networks
When it happens
Trigger: nathole.Prepare(stunServers, opts) where all STUN servers fail: unreachable/dead servers, UDP fully blocked by the local firewall, DNS failure resolving server hostnames.
Common situations: Running xtcp on hosts with outbound UDP denied; empty or stale natHoleSTUNServer config; captive portals or VPNs swallowing UDP; containers with restricted networking.
Related errors
- wait response from stun server timeout
- no external address found
- not enough addresses
- classify client nat feature error: %v
- classify visitor nat feature error: %v
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/725a60b2e1b90366.
Report an issue: GitHub.