XTLS/Xray-core · warning · errors.Error

connection ends

Error message

connection ends

What it means

Outer wrapper for failures from the http outbound's bidirectional task group (requestFunc uplink / responseFunc downlink). Any mid-connection error — client disconnect, proxy closing the tunnel, policy timeout in timer.SetTimeout — is reported as "connection ends" with the true cause chained underneath.

Source

Thrown at proxy/http/client.go:160

	}, p.Timeouts.ConnectionIdle)

	requestFunc := func() error {
		defer timer.SetTimeout(p.Timeouts.DownlinkOnly)
		return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer))
	}
	responseFunc := func() error {
		ob.CanSpliceCopy = 1
		defer timer.SetTimeout(p.Timeouts.UplinkOnly)
		return buf.Copy(buf.NewReader(conn), 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
}

// fillRequestHeader will fill out the template of the headers
func fillRequestHeader(ctx context.Context, header []*Header) ([]*Header, error) {
	if len(header) == 0 {
		return header, nil
	}

	inbound := session.InboundFromContext(ctx)
	outbounds := session.OutboundsFromContext(ctx)
	ob := outbounds[len(outbounds)-1]

	if inbound == nil || ob == nil {
		return nil, errors.New("missing inbound or outbound metadata from context")
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Unwrap to find the underlying copy error before deciding severity
  2. Treat io.EOF/context.Canceled bases as normal teardown
  3. Raise policy timeouts (uplinkOnly/downlinkOnly) for idle-prone traffic through HTTP proxies
  4. If the proxy kills tunnels early, enable periodic traffic or shorter app keepalives
Defensive patterns

Strategy: try-catch

Type guard

```go
func isBenignTeardown(err error) bool {
    return errors.Is(err, io.EOF) || errors.Is(err, context.Canceled)
}
```

Try / catch

```go
if err := c.Process(ctx, link, dialer); err != nil && !isBenignTeardown(err) {
    log.Warn().Err(errors.Unwrap(err)).Msg("http outbound connection failed")
}
```

Prevention

When it happens

Trigger: Established CONNECT tunnel where either copy direction fails: proxy RSTs the tunnel, client closes, or uplinkOnly/downlinkOnly timeouts expire while the tunnel is idle.

Common situations: Idle keepalive-heavy traffic through an aggressive proxy, mobile clients dropping, timeouts inherited from policy level 0 (default) being too short.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/0730d2b6bf53eb96. Report an issue: GitHub.