{"record":{"id":"18589cba9a26b5d4","repo":"netbirdio/netbird","slug":"remote-conn-s","errorCode":null,"errorMessage":"remote conn: %s","messagePattern":"remote conn: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/iface/wgproxy/udp/proxy.go","lineNumber":191,"sourceCode":"\tdefer p.closeMu.Unlock()\n\n\t// prevent double close\n\tif p.closed {\n\t\treturn nil\n\t}\n\n\tp.closeListener.SetCloseListener(nil)\n\tp.closed = true\n\n\tp.cancel()\n\n\tp.pausedCond.L.Lock()\n\tp.paused = false\n\tp.pausedCond.Signal()\n\tp.pausedCond.L.Unlock()\n\n\tif err := p.remoteConn.Close(); err != nil && !errors.Is(err, net.ErrClosed) {\n\t\tresult = multierror.Append(result, fmt.Errorf(\"remote conn: %s\", err))\n\t}\n\n\tif err := p.localConn.Close(); err != nil {\n\t\tresult = multierror.Append(result, fmt.Errorf(\"local conn: %s\", err))\n\t}\n\n\tif p.srcFakerConn != nil {\n\t\tif err := p.srcFakerConn.Close(); err != nil {\n\t\t\tresult = multierror.Append(result, fmt.Errorf(\"src faker raw conn: %s\", err))\n\t\t}\n\t}\n\n\treturn cerrors.FormatErrorOrNil(result)\n}\n\n// proxyToRemote proxies from Wireguard to the RemoteKey\nfunc (p *WGUDPProxy) proxyToRemote(ctx context.Context) {\n\tdefer func() {","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/iface/wgproxy/udp/proxy.go#L173-L209","documentation":"Appended to the multierror returned by WGUDPProxy.close() when remoteConn.Close() fails with anything other than net.ErrClosed. The remote conn is the relay/TURN connection. net.ErrClosed is explicitly filtered, so this fires for genuine errors: socket in a bad state, close(2) returning EBADF, or a custom net.Conn implementation whose Close returns its own error (e.g. relay framing teardown failure).","triggerScenarios":"Teardown racing with the proxy loops: proxyToRemote/proxyToLocal both defer close(), and any external CloseConn call can interleave; underlying TURN conn already terminated by the relay; custom conn wrappers erroring on double cleanup.","commonSituations":"Seen in logs as 'error in proxy to remote loop' or returned from CloseConn during peer disconnect/reconnect cycles. Usually benign - the socket is going away anyway - but it can mask an fd leak if Close genuinely failed.","solutions":["Treat as teardown noise unless it repeats for the same peer: the double-close case is already filtered via net.ErrClosed","If it persists, inspect the wrapped message to identify which net.Conn implementation is failing (pion relay conn vs plain UDP)","Verify fd count over time (`ls /proc/$(pgrep -x netbird)/fd | wc -l`) to rule out a leak from failed closes"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := p.close(); err != nil {\n    var merr *multierror.Error\n    if errors.As(err, &merr) {\n        for _, e := range merr.Errors {\n            if strings.HasPrefix(e.Error(), \"remote conn:\") {\n                log.Debugf(\"remote conn close noise: %v\", e) // teardown, socket is dead anyway\n                continue\n            }\n            log.Warnf(\"proxy close: %v\", e)\n        }\n    }\n}","preventionTips":["Rely on the built-in net.ErrClosed filter; do not pre-close the remote conn out from under the proxy","Log close-path multierrors at debug in normal operation to keep disconnect logs readable","Track fd counts if close errors correlate with relay churn"],"tags":["go","netbird","udp-proxy","teardown","multierror"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}