{"record":{"id":"62fcdd81e25b148f","repo":"fatedier/frp","slug":"listen-local-udp-addr-error-v","errorCode":null,"errorMessage":"listen local udp addr error: %v","messagePattern":"listen local udp addr error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nathole/nathole.go","lineNumber":140,"sourceCode":"\t\treturn nil, fmt.Errorf(\"discover error: %v\", err)\n\t}\n\tif len(addrs) < 2 {\n\t\treturn nil, fmt.Errorf(\"discover error: not enough addresses\")\n\t}\n\n\tlocalIPs, _ := ListLocalIPsForNatHole(10)\n\tnatFeature, err := ClassifyNATFeature(addrs, localIPs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"classify nat feature error: %v\", err)\n\t}\n\n\tladdr, err := net.ResolveUDPAddr(\"udp4\", localAddr.String())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"resolve local udp addr error: %v\", err)\n\t}\n\tlistenConn, err := net.ListenUDP(\"udp4\", laddr)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"listen local udp addr error: %v\", err)\n\t}\n\n\t// Apply NAT traversal options\n\tvar assistedAddrs []string\n\tif !opts.DisableAssistedAddrs {\n\t\tassistedAddrs = make([]string, 0, len(localIPs))\n\t\tfor _, ip := range localIPs {\n\t\t\tassistedAddrs = append(assistedAddrs, net.JoinHostPort(ip, strconv.Itoa(laddr.Port)))\n\t\t}\n\t}\n\treturn &PrepareResult{\n\t\tAddrs:         addrs,\n\t\tAssistedAddrs: assistedAddrs,\n\t\tListenConn:    listenConn,\n\t\tNatType:       natFeature.NatType,\n\t\tBehavior:      natFeature.Behavior,\n\t}, nil\n}","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/nathole/nathole.go#L122-L158","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nres1, _ := nathole.Prepare(servers, opts)\nres2, _ := nathole.Prepare(servers, opts) // may bind same local port -> fails\n\n// after\nres1, _ := nathole.Prepare(servers, opts)\n// ... use res1 ...\nres1.ListenConn.Close() // free the port before preparing again\nres2, _ := nathole.Prepare(servers, opts)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"res, err := nathole.Prepare(servers, opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"listen local udp addr error\") {\n        if errors.Is(err, syscall.EADDRINUSE) {\n            // close prior ListenConn or wait for the port, then retry\n        }\n    }\n}","preventionTips":["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"],"tags":["go","frp","nathole","network","sockets","resource"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}