fatedier/frp · error
not enough addresses
Error message
not enough addresses
What it means
Thrown by ClassifyNATFeature in pkg/nathole/classify.go when the addresses slice has one or zero entries. NAT classification compares the IP and port observed from at least two different STUN observations to infer endpoint-independent vs address-dependent mapping behavior; with a single observation there is nothing to compare, so classification is impossible.
Source
Thrown at pkg/nathole/classify.go:44
HardNAT = "HardNAT"
BehaviorNoChange = "BehaviorNoChange"
BehaviorIPChanged = "BehaviorIPChanged"
BehaviorPortChanged = "BehaviorPortChanged"
BehaviorBothChanged = "BehaviorBothChanged"
)
type NatFeature struct {
NatType string
Behavior string
PortsDifference int
RegularPortsChange bool
PublicNetwork bool
}
func ClassifyNATFeature(addresses []string, localIPs []string) (*NatFeature, error) {
if len(addresses) <= 1 {
return nil, fmt.Errorf("not enough addresses")
}
natFeature := &NatFeature{}
ipChanged := false
portChanged := false
var baseIP, basePort string
var portMax, portMin int
for _, addr := range addresses {
ip, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
portNum, err := strconv.Atoi(port)
if err != nil {
return nil, err
}
if slices.Contains(localIPs, ip) {
natFeature.PublicNetwork = trueView on GitHub (pinned to 6c8a8d0a97)
Solutions
- Ensure Discover(stunServers, ...) is given at least two reachable STUN servers and returns >= 2 addresses before classifying
- Check natFeature/stun server reachability: verify natHoleSTUNServer in frps.toml points to working STUN endpoints
- Retry discovery — transient UDP loss can drop one observation
- If calling ClassifyNATFeature yourself, guard with len(addresses) < 2 and skip classification
Example fix
// before
feature, err := ClassifyNATFeature(addrs, localIPs)
// after
if len(addrs) < 2 {
return nil, fmt.Errorf("need at least 2 discovered addresses, got %d", len(addrs))
}
feature, err := ClassifyNATFeature(addrs, localIPs) Defensive patterns
Strategy: validation
Validate before calling
if len(addresses) < 2 {
return nil, fmt.Errorf("classification needs >=2 addresses, got %d", len(addresses))
} Try / catch
feature, err := nathole.ClassifyNATFeature(addrs, localIPs)
if err != nil {
if strings.Contains(err.Error(), "not enough addresses") {
// re-run discovery with more STUN servers before retrying
}
return err
} Prevention
- Ensure discovery returns >=2 addresses before classifying
- Configure multiple reachable STUN servers
- Validate each address parses as host:port before passing in
When it happens
Trigger: Calling ClassifyNATFeature(addresses, localIPs) with len(addresses) <= 1. In frp this happens when Discover() returned only one mapped address because only one STUN server responded, or when a caller passes a single hard-coded address instead of the multi-server discovery result.
Common situations: STUN servers misconfigured or unreachable so discovery yields one address; firewalls blocking UDP to all but one STUN endpoint; custom code that calls ClassifyNATFeature directly without first checking the discovery result length; symmetric NAT environments where the second STUN query fails.
Related errors
- classify client nat feature error: %v
- classify visitor nat feature error: %v
- discover error: not enough addresses
- wait response from stun server timeout
- no external address found
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/1dffbc3cddf834a8.
Report an issue: GitHub.