{"record":{"id":"0601c592f71ff171","repo":"XTLS/Xray-core","slug":"cannot-dial-remote-address-0601c5","errorCode":null,"errorMessage":"cannot dial remote address ","messagePattern":"cannot dial remote address ","errorType":"console","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"app/observatory/observer.go","lineNumber":148,"sourceCode":"func (o *Observer) probe(outbound string) ProbeResult {\n\terrorCollectorForRequest := newErrorCollector()\n\n\thttpTransport := http.Transport{\n\t\tProxy: func(*http.Request) (*url.URL, error) {\n\t\t\treturn nil, nil\n\t\t},\n\t\tDialContext: func(ctx context.Context, network string, addr string) (net.Conn, error) {\n\t\t\tvar connection net.Conn\n\t\t\ttaskErr := task.Run(ctx, func() error {\n\t\t\t\t// MUST use Xray's built in context system\n\t\t\t\tdest, err := v2net.ParseDestination(network + \":\" + addr)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn errors.New(\"cannot understand address\").Base(err)\n\t\t\t\t}\n\t\t\t\ttrackedCtx := session.TrackedConnectionError(o.ctx, errorCollectorForRequest)\n\t\t\t\tconn, err := tagged.Dialer(trackedCtx, o.dispatcher, dest, outbound)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn errors.New(\"cannot dial remote address \", dest).Base(err)\n\t\t\t\t}\n\t\t\t\tconnection = conn\n\t\t\t\treturn nil\n\t\t\t})\n\t\t\tif taskErr != nil {\n\t\t\t\treturn nil, errors.New(\"cannot finish connection\").Base(taskErr)\n\t\t\t}\n\t\t\treturn connection, nil\n\t\t},\n\t\tTLSHandshakeTimeout: time.Second * 5,\n\t}\n\thttpClient := &http.Client{\n\t\tTransport: &httpTransport,\n\t\tCheckRedirect: func(req *http.Request, via []*http.Request) error {\n\t\t\treturn http.ErrUseLastResponse\n\t\t},\n\t\tJar:     nil,\n\t\tTimeout: time.Second * 5,","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/observatory/observer.go#L130-L166","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// consumers of ProbeResult: treat dial failure as node-down and switch traffic, don't crash\nif !result.Alive {\n    router.MarkOutboundDead(tag)\n    log.WithError(chainRoot(result.LastErrorReason)).Warn(\"outbound probe failed\")\n}","preventionTips":["Verify outbound credentials and streamSettings before enabling observation.","Pair observatory with balancer/routing so dead outbounds are bypassed automatically."],"tags":["go","xray","observatory","outbound","proxy"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}