XTLS/Xray-core · error
cannot finish connection
Error message
cannot finish connection
What it means
Generic wrapper returned by the geodata dialer when task.Run (which encapsulates ParseDestination + tagged.Dialer) exits with any error. It is the outermost frame of the dial path; the specific cause is always in the chained Base error ('cannot understand address' or 'cannot dial remote address ...').
Source
Thrown at app/geodata/download.go:85
dial := func(ctx context.Context, network, address string) (net.Conn, error) {
var conn net.Conn
err := task.Run(ctx, func() error {
if tagged.Dialer == nil {
return errors.New("tagged dialer is not initialized")
}
dest, err := net.ParseDestination(network + ":" + address)
if err != nil {
return errors.New("cannot understand address").Base(err)
}
c, err := tagged.Dialer(baseCtx, dispatcher, dest, outbound)
if err != nil {
return errors.New("cannot dial remote address ", dest).Base(err)
}
conn = c
return nil
})
if err != nil {
return nil, errors.New("cannot finish connection").Base(err)
}
return &idleConn{
Conn: conn,
}, nil
}
if isHTTPS {
return &http.Client{
Transport: &http2.Transport{
DialTLSContext: func(ctx context.Context, network string, address string, cfg *tls.Config) (net.Conn, error) {
conn, err := dial(ctx, network, address)
if err != nil {
return nil, err
}
host, _, _ := net.SplitHostPort(address)
tlsConn := utls.UClient(conn, &utls.Config{ServerName: host}, utls.HelloChrome_Auto)
handshakeCtx, cancel := context.WithTimeout(ctx, idleTimeout)
defer cancel()
if err := tlsConn.HandshakeContext(handshakeCtx); err != nil {View on GitHub (pinned to 7d214f8b09)
Solutions
- Inspect err.(*errors.Error).Base()/unwrap chain — the real cause is 'cannot understand address' or 'cannot dial remote address'
- Fix the underlying cause per that inner error (URL format or outbound reachability)
- Retry after network conditions change if the base cause is a transient connect failure
Defensive patterns
Strategy: try-catch
Try / catch
resp, err := client.Get(assetURL)
if err != nil {
var xe *errors.Error
if errors.As(err, &xe) && strings.Contains(xe.Message(), "cannot finish connection") {
cause := xe.Base() // 'cannot understand address' or 'cannot dial remote address'
log.Warn("geodata dial failed: ", cause)
}
return err
} Prevention
- Always unwrap to the Base cause before acting on this wrapper error
- Treat it as a routing layer symptom, not a root cause
When it happens
Trigger: Any failure inside the dial closure passed to task.Run for a geodata HTTP(S) request — address parse failure or dial failure — resurfaces from http.Client as this wrapped error.
Common situations: Same situations as errors 22 and 23: bad asset URL, missing/unreachable outbound, or network failure; users see this message first in logs and must inspect the chained cause.
Related errors
- connection idle timeout
- cannot understand address
- cannot dial remote address
- redirected to non-https URL:
- stopped after 10 redirects
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/9b308fd7365a345a.
Report an issue: GitHub.