{"record":{"id":"fcc3b993005be157","repo":"fatedier/frp","slug":"acquire-port-d-error-v","errorCode":null,"errorMessage":"acquire port %d error: %v","messagePattern":"acquire port (.+?) error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/proxy/udp.go","lineNumber":82,"sourceCode":"}\n\nfunc NewUDPProxy(baseProxy *BaseProxy) Proxy {\n\tunwrapped, ok := baseProxy.GetConfigurer().(*v1.UDPProxyConfig)\n\tif !ok {\n\t\treturn nil\n\t}\n\tbaseProxy.usedPortsNum = 1\n\treturn &UDPProxy{\n\t\tBaseProxy: baseProxy,\n\t\tcfg:       unwrapped,\n\t}\n}\n\nfunc (pxy *UDPProxy) Run() (remoteAddr string, err error) {\n\txl := pxy.xl\n\tpxy.realBindPort, err = pxy.rc.UDPPortManager.Acquire(pxy.name, pxy.cfg.RemotePort)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"acquire port %d error: %v\", pxy.cfg.RemotePort, err)\n\t}\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tpxy.rc.UDPPortManager.Release(pxy.realBindPort)\n\t\t}\n\t}()\n\n\tremoteAddr = fmt.Sprintf(\":%d\", pxy.realBindPort)\n\tpxy.cfg.RemotePort = pxy.realBindPort\n\taddr, errRet := net.ResolveUDPAddr(\"udp\", net.JoinHostPort(pxy.serverCfg.ProxyBindAddr, strconv.Itoa(pxy.realBindPort)))\n\tif errRet != nil {\n\t\terr = errRet\n\t\treturn\n\t}\n\tudpConn, errRet := net.ListenUDP(\"udp\", addr)\n\tif errRet != nil {\n\t\terr = errRet\n\t\txl.Warnf(\"listen udp port error: %v\", err)","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/server/proxy/udp.go#L64-L100","documentation":"UDPProxy.Run asks the server's UDPPortManager to Acquire the requested remote port; failure is wrapped as \"acquire port %d error\". Acquire fails when the port is already bound, not allowed by allowPorts, or no port is available for allocation. The deferred Release unwinds the partial allocation, so the proxy start aborts cleanly.","triggerScenarios":"remotePort already used by another UDP proxy or another process on the server; remotePort outside the server's allowPorts range; remotePort = 0 (random allocation) but the allowed range is exhausted.","commonSituations":"Hard-coding the same remotePort in several client configs; the port occupied by an unrelated service on the host; firewall/allowPorts policy on frps that the client config ignores.","solutions":["Pick a different, unoccupied remotePort or set remotePort = 0 to let frps allocate a free one","Check frps allowPorts and move the port inside the permitted range","On the server, verify nothing else binds that UDP port (ss -uln) and that the previous proxy using it is gone"],"exampleFix":"# before\n[[proxies]]\ntype = \"udp\"\nremotePort = 6000   # taken\n\n# after\n[[proxies]]\ntype = \"udp\"\nremotePort = 0      # frps picks a free UDP port","handlingStrategy":"validation","validationCode":"// Before starting, check the UDP port is free when a fixed remotePort is set.\nif cfg.RemotePort != 0 {\n    if c, err := net.ListenPacket(\"udp\", fmt.Sprintf(\":%d\", cfg.RemotePort)); err != nil {\n        return fmt.Errorf(\"remotePort %d unavailable: %w\", cfg.RemotePort, err)\n    } else { c.Close() }\n}","typeGuard":null,"tryCatchPattern":"if _, err := pxy.Run(); err != nil && strings.Contains(err.Error(), \"acquire port\") {\n    // release-and-retry once with remotePort = 0 for dynamic allocation\n}","preventionTips":["Prefer remotePort = 0 for UDP unless a fixed port is required","Keep a single inventory of allocated ports across all frpc configs pointing at one frps","Cross-check server allowPorts before hard-coding a remotePort"],"tags":["frps","udp","port-allocation","network"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}