XTLS/Xray-core · error · errors.Error
cannot dial remote address
Error message
cannot dial remote address
What it means
Thrown in app/observatory/observer.go:148 when tagged.Dialer — Xray's outbound dispatch dialer — fails to establish the connection from the probed outbound to the probe destination. This is the direct 'this outbound could not connect' signal for the observatory, with the failing destination embedded in the message.
Source
Thrown at app/observatory/observer.go:148
func (o *Observer) probe(outbound string) ProbeResult {
errorCollectorForRequest := newErrorCollector()
httpTransport := http.Transport{
Proxy: func(*http.Request) (*url.URL, error) {
return nil, nil
},
DialContext: func(ctx context.Context, network string, addr string) (net.Conn, error) {
var connection net.Conn
taskErr := task.Run(ctx, func() error {
// MUST use Xray's built in context system
dest, err := v2net.ParseDestination(network + ":" + addr)
if err != nil {
return errors.New("cannot understand address").Base(err)
}
trackedCtx := session.TrackedConnectionError(o.ctx, errorCollectorForRequest)
conn, err := tagged.Dialer(trackedCtx, o.dispatcher, dest, outbound)
if err != nil {
return errors.New("cannot dial remote address ", dest).Base(err)
}
connection = conn
return nil
})
if taskErr != nil {
return nil, errors.New("cannot finish connection").Base(taskErr)
}
return connection, nil
},
TLSHandshakeTimeout: time.Second * 5,
}
httpClient := &http.Client{
Transport: &httpTransport,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
Jar: nil,
Timeout: time.Second * 5,View on GitHub (pinned to 7d214f8b09)
Solutions
- Verify the outbound server is up and credentials (id/password) match on both ends.
- Check streamSettings (TLS/REALITY settings, SNI, port) of the failing outbound.
- Ensure routing rules do not intercept the probe traffic (destination is the probe URL) and loop it incorrectly.
- Look at the chained Base error for the precise protocol-level failure.
Defensive patterns
Strategy: fallback
Try / catch
// consumers of ProbeResult: treat dial failure as node-down and switch traffic, don't crash
if !result.Alive {
router.MarkOutboundDead(tag)
log.WithError(chainRoot(result.LastErrorReason)).Warn("outbound probe failed")
} Prevention
- Verify outbound credentials and streamSettings before enabling observation.
- Pair observatory with balancer/routing so dead outbounds are bypassed automatically.
When it happens
Trigger: The selected outbound handler's proxy handshake or underlying transport fails while the probe connection is dispatched: server down, refused TCP connection, wrong credentials, proxy protocol error, or routing rule sending the probe to a black hole.
Common situations: The single most common observatory error in production: an outbound VMess/Trojan/Shadowsocks server is offline or its credentials changed, and the observer immediately reports the outbound dead with this as the underlying cause.
Related errors
- cannot finish connection
- failed to process outbound traffic
- underlying connection error
- failed to produce report
- cannot understand address
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/0601c592f71ff171.
Report an issue: GitHub.