{"record":{"id":"e4b5ed81372731d0","repo":"XTLS/Xray-core","slug":"connection-ends-e4b5ed","errorCode":null,"errorMessage":"connection ends","messagePattern":"connection ends","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/socks/client.go","lineNumber":171,"sourceCode":"\t\t\tdefer timer.SetTimeout(p.Timeouts.DownlinkOnly)\n\t\t\twriter := &UDPWriter{Writer: udpConn, Request: request}\n\t\t\treturn buf.Copy(link.Reader, writer, buf.UpdateActivity(timer))\n\t\t}\n\t\tresponseFunc = func() error {\n\t\t\tob.CanSpliceCopy = 1\n\t\t\tdefer timer.SetTimeout(p.Timeouts.UplinkOnly)\n\t\t\treader := &UDPReader{Reader: udpConn}\n\t\t\treturn buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))\n\t\t}\n\t}\n\n\tif newCtx != nil {\n\t\tctx = newCtx\n\t}\n\n\tresponseDonePost := task.OnSuccess(responseFunc, task.Close(link.Writer))\n\tif err := task.Run(ctx, requestFunc, responseDonePost); err != nil {\n\t\treturn errors.New(\"connection ends\").Base(err)\n\t}\n\n\treturn nil\n}\n\nfunc init() {\n\tcommon.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {\n\t\treturn NewClient(ctx, config.(*ClientConfig))\n\t}))\n}\n","sourceCodeStart":153,"sourceCodeEnd":182,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/socks/client.go#L153-L182","documentation":"Thrown by the SOCKS outbound client (proxy/socks/client.go:171) when task.Run, which concurrently runs the uplink copy (link.Reader -> SOCKS connection / UDP writer) and the downlink copy (SOCKS connection / UDP reader -> link.Writer), returns an error. It is a generic wrapper: 'connection ends' means the proxied tunnel terminated before normal completion. The Base error carries the real cause, such as idle-timeout cancellation (signal.CancelAfterInactivity), a TCP RST/EOF from the remote SOCKS server, or a UDP dial/read failure.","triggerScenarios":"Calling the SOCKS outbound Process() for a TCP or UDP request and having any of these fail: buf.Copy in requestFunc or responseFunc, the UDP dial in the UDP branch, or the context being cancelled by the inactivity timer (policy timeouts: connectionIdle, downlinkOnly, upplinkOnly). Also triggered when the remote SOCKS server closes the connection mid-stream.","commonSituations":"Aggressive policy timeouts (small connectionIdle values) killing quiet connections; remote proxy server restarting or dropping the session; flaky NAT dropping long-lived UDP sessions; client-side cancellation of a request; network switch during an active connection.","solutions":["Inspect the wrapped error (err via errors.Unwrap / log output) to find the underlying cause before changing anything.","If connections die during idle periods, raise connectionIdle/downlinkOnly/uplinkOnly timeouts in the policy settings of the outbound's streamSettings/user level.","If the remote SOCKS server resets the connection, check that server's logs and health; verify the address/credentials in the outbound config.","For UDP failures, confirm the remote server supports UDP associate and the network path allows UDP (no blocking NAT/firewall).","Treat as transient and reconnect at the application layer if the base error is a timeout or reset."],"exampleFix":"// before: policy with aggressive idle timeout causes frequent 'connection ends'\n\"policy\": { \"levels\": { \"0\": { \"handshake\": 4, \"connIdle\": 30, \"uplinkOnly\": 0, \"downlinkOnly\": 0 } } }\n\n// after: allow idle periods without killing the tunnel\n\"policy\": { \"levels\": { \"0\": { \"handshake\": 4, \"connIdle\": 300, \"uplinkOnly\": 60, \"downlinkOnly\": 60 } } }","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// In Go, check err from the outbound Process path and inspect the chain\nif err != nil {\n    if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) || strings.Contains(err.Error(), \"connection ends\") {\n        // transient tunnel termination: reconnect / retry request\n        return retryWithBackoff()\n    }\n    return err\n}","preventionTips":["Set policy timeouts (connIdle, uplinkOnly, downlinkOnly) appropriate to the traffic pattern before deploying.","Monitor base errors in logs to distinguish timeouts from resets.","Implement idempotent, reconnecting clients so a dropped tunnel self-heals."],"tags":["network","socks","proxy","timeout","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}