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

  1. Read the wrapped error (it is chained with .Base(err)) to see whether it is DNS, timeout, TLS, or unix-dial specific
  2. 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
  3. For https targets, verify the certificate is trusted or fetch over http within a trusted network
  4. 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

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


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