XTLS/Xray-core · error
failed to dial to
Error message
failed to dial to
What it means
Returned when http.Client.Do fails while fetching remote config content in FetchHTTPContent. This covers every transport-level failure: DNS resolution errors, refused/timeout connections, TLS handshake failures, and unreachable Unix/abstract sockets (the transport dials 'unix' when socketPath is non-empty). The original error is attached via Base(err), so the cause is preserved.
Source
Thrown at main/confloader/external/external.go:82
}
if socketPath != "" {
dialAddr := utils.ResolveSocketPath(socketPath)
client.Transport = &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
var d net.Dialer
return d.DialContext(ctx, "unix", dialAddr)
},
}
}
resp, err := client.Do(&http.Request{
Method: "GET",
URL: parsedTarget,
Close: true,
})
if err != nil {
return nil, errors.New("failed to dial to ", target).Base(err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, errors.New("unexpected HTTP status code: ", resp.StatusCode)
}
content, err := buf.ReadAllToBytes(resp.Body)
if err != nil {
return nil, errors.New("failed to read HTTP response").Base(err)
}
return content, nil
}
// isRemoteSource reports whether arg should be fetched via HTTP (regular
// network or Unix socket) rather than read from the local filesystem.
// Recognized forms:View on GitHub (pinned to 7d214f8b09)
Solutions
- Read the wrapped error (it is chained with .Base(err)) to see whether it is DNS, timeout, TLS, or unix-dial specific
- For socket targets, verify the socket exists and is listening: ls -l /path/to/socket.sock or ss -x | grep <name>; start the serving process first
- For https targets, verify the certificate is trusted or fetch over http within a trusted network
- Verify network/DNS availability from the machine (curl the same URL) and increase reachability before retrying
Example fix
# before xray run -config http://10.0.0.5:8080/config.json # server down -> failed to dial to ... # after # confirm the endpoint answers, then run curl -f http://10.0.0.5:8080/config.json && xray run -config http://10.0.0.5:8080/config.json
Defensive patterns
Strategy: retry
Validate before calling
// for socket targets
if _, err := os.Stat(sockPath); err != nil {
return fmt.Errorf("socket %s not ready: %w", sockPath, err)
}
// for https targets
if conn, err := net.DialTimeout("tcp", hostPort, 3*time.Second); err == nil { conn.Close() } Try / catch
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() { backoff.Retry(fetch, 3) } Prevention
- Health-check remote config endpoints before boot (curl -f)
- Start socket-serving processes before Xray in service unit ordering (After=/Requires=)
- Cache the last good config locally so boot survives a temporarily unreachable endpoint
When it happens
Trigger: client.Do(&http.Request{Method:"GET", URL:parsedTarget, Close:true}) failing: host down or unresolvable, 30s timeout exceeded, TLS certificate mismatch on https, or a socket target whose socket file does not exist / is not listening (abstract socket name wrong on Linux/Android).
Common situations: Fetch happens at startup so misconfigurations surface as boot failure; typical cases are pointing -config at a dead URL, a proxy-side Unix socket (e.g. a local API daemon) not started yet, DNS failure in a sandboxed environment, or self-signed certs when fetching over https.
Related errors
- empty HTTP header value: + key
- invalid URL:
- unexpected HTTP status code:
- failed to read HTTP response
- outbound failed to relay connection
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/11fd2f9a0f44ba8f.
Report an issue: GitHub.