{"record":{"id":"6f0885105fcd3684","repo":"netbirdio/netbird","slug":"local-conn-s","errorCode":null,"errorMessage":"local conn: %s","messagePattern":"local conn: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/iface/wgproxy/udp/proxy.go","lineNumber":195,"sourceCode":"\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() {\n\t\tif err := p.close(); err != nil {\n\t\t\tlog.Warnf(\"error in proxy to remote loop: %s\", err)\n\t\t}\n\t}()","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/iface/wgproxy/udp/proxy.go#L177-L213","documentation":"Appended to the close() multierror when the local UDP conn (the dial to the agent's own WireGuard listen port made in AddTurnConn) fails to close. Unlike the remote conn branch, net.ErrClosed is NOT filtered here, but the closed flag plus closeMu make double-close impossible from close() itself, so in practice this only fires on real close errors or on races where something else closed localConn.","triggerScenarios":"localConn already dead (local WG listener gone, e.g. interface recreate during reconnect) and the socket reporting an error on close; external code closing the conn out from under the proxy.","commonSituations":"Reconnect cycles where the WireGuard interface is rebuilt; shutdown ordering issues between the engine and proxy manager. Almost always transient noise accompanying a legitimate disconnect.","solutions":["Ignore one-off occurrences during netbird down/reconnects","If the message pairs with relay failures, restart the agent to rewire proxy and interface cleanly","Check for custom integrations that close conns they handed to AddTurnConn"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := p.localConn.Close(); err != nil && !errors.Is(err, net.ErrClosed) {\n    result = multierror.Append(result, fmt.Errorf(\"local conn: %w\", err)) // use %w so callers can errors.Is\n}","preventionTips":["Never close localConn externally; always route teardown through CloseConn/close so the closed flag applies","During interface rebuilds, expect this error once and drain proxies before recreating the WG interface","Use %w instead of %s when wrapping so callers can match sentinel errors"],"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"}