XTLS/Xray-core · warning
connection ends
Error message
connection ends
What it means
Aggregate error returned by the trojan TCP relay when task.Run finishes with a failure in either the request or response pipe (wraps [724] or [725] typically). Before returning it interrupts both link ends so no goroutine or buffer leaks. It marks the end of a trojan connection, not a protocol defect per se.
Source
Thrown at proxy/trojan/server.go:358
return errors.New("failed to transfer request").Base(err)
}
return nil
}
responseDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
if err := buf.Copy(link.Reader, clientWriter, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to write response").Base(err)
}
return nil
}
requestDonePost := task.OnSuccess(requestDone, task.Close(link.Writer))
if err := task.Run(ctx, requestDonePost, responseDone); err != nil {
common.Must(common.Interrupt(link.Reader))
common.Must(common.Interrupt(link.Writer))
return errors.New("connection ends").Base(err)
}
return nil
}
func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.Session, connection stat.Connection, iConn stat.Connection, napfb map[string]map[string]map[string]*Fallback, first *buf.Buffer, firstLen int64, reader buf.Reader) error {
if err := connection.SetReadDeadline(time.Time{}); err != nil {
errors.LogWarningInner(ctx, err, "unable to set back read deadline")
}
errors.LogInfoInner(ctx, err, "fallback starts")
name := ""
alpn := ""
if tlsConn, ok := iConn.(*tls.Conn); ok {
cs := tlsConn.ConnectionState()
name = cs.ServerName
alpn = cs.NegotiatedProtocol
errors.LogInfo(ctx, "realName = "+name)View on GitHub (pinned to 7d214f8b09)
Solutions
- Inspect the Base error chain to see which pipe failed and why
- If it floods the log during shutdown, reduce log level for the trojan inbound
- Fix the underlying copy failure per [724]/[725] guidance if it happens during active traffic
Defensive patterns
Strategy: try-catch
Try / catch
if err := task.Run(ctx, requestDonePost, responseDone); err != nil {
common.Must(common.Interrupt(link.Reader))
common.Must(common.Interrupt(link.Writer))
return errors.New("connection ends").Base(err)
} Prevention
- Read the Base chain first; this error is only an aggregator for [724]/[725]
- During planned shutdown expect a burst of these; lower loglevel before restarting
- Never retry the whole connection automatically — clients own reconnection semantics
When it happens
Trigger: Either requestDone or responseDone returned an error — i.e. any broken pipe during relaying — or the context was cancelled by the idle timer and a copy was treated as failure.
Common situations: Seen in bulk at server restart/shutdown (all connections torn down), during network churn, or after policy timeouts.
Related errors
- unexpected EOF
- failed to transfer request
- failed to write response
- failed to fallback request payload
- failed to deliver response payload
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/2a92be9573a39382.
Report an issue: GitHub.