XTLS/Xray-core · error
connection ends
Error message
connection ends
What it means
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.
Source
Thrown at proxy/socks/client.go:171
defer timer.SetTimeout(p.Timeouts.DownlinkOnly)
writer := &UDPWriter{Writer: udpConn, Request: request}
return buf.Copy(link.Reader, writer, buf.UpdateActivity(timer))
}
responseFunc = func() error {
ob.CanSpliceCopy = 1
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
reader := &UDPReader{Reader: udpConn}
return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))
}
}
if newCtx != nil {
ctx = newCtx
}
responseDonePost := task.OnSuccess(responseFunc, task.Close(link.Writer))
if err := task.Run(ctx, requestFunc, responseDonePost); err != nil {
return errors.New("connection ends").Base(err)
}
return nil
}
func init() {
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewClient(ctx, config.(*ClientConfig))
}))
}
View on GitHub (pinned to 7d214f8b09)
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.
Example fix
// before: policy with aggressive idle timeout causes frequent 'connection ends'
"policy": { "levels": { "0": { "handshake": 4, "connIdle": 30, "uplinkOnly": 0, "downlinkOnly": 0 } } }
// after: allow idle periods without killing the tunnel
"policy": { "levels": { "0": { "handshake": 4, "connIdle": 300, "uplinkOnly": 60, "downlinkOnly": 60 } } } Defensive patterns
Strategy: retry
Try / catch
// In Go, check err from the outbound Process path and inspect the chain
if err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) || strings.Contains(err.Error(), "connection ends") {
// transient tunnel termination: reconnect / retry request
return retryWithBackoff()
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- insufficient header
- failed to write auth response
- failed to read request
- failed to create unexpected ip matcher
- connection idle timeout
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/e4b5ed81372731d0.
Report an issue: GitHub.