XTLS/Xray-core · error · errors.Error
failed to find an available destination
Error message
failed to find an available destination
What it means
setUpHTTPTunnel was retried with ExponentialBackoff(5, 100ms) and every attempt failed — dialing the proxy, TLS/ALPN negotiation, the CONNECT round-trip, or writing the first payload. After exhausting retries the last error is wrapped as "failed to find an available destination".
Source
Thrown at proxy/http/client.go:116
header, err := fillRequestHeader(ctx, c.header)
if err != nil {
return errors.New("failed to fill out header").Base(err)
}
if err := retry.ExponentialBackoff(5, 100).On(func() error {
netConn, err := setUpHTTPTunnel(ctx, dest, targetAddr, user, dialer, header, firstPayload)
if netConn != nil {
if _, ok := netConn.(*http2Conn); !ok {
if _, err := netConn.Write(firstPayload); err != nil {
netConn.Close()
return err
}
}
conn = stat.Connection(netConn)
}
return err
}); err != nil {
return errors.New("failed to find an available destination").Base(err)
}
defer func() {
if err := conn.Close(); err != nil {
errors.LogInfoInner(ctx, err, "failed to closed connection")
}
}()
p := c.policyManager.ForLevel(0)
if user != nil {
p = c.policyManager.ForLevel(user.Level)
}
var newCtx context.Context
var newCancel context.CancelFunc
if session.TimeoutOnlyFromContext(ctx) {
newCtx, newCancel = context.WithCancel(context.Background())
}View on GitHub (pinned to 7d214f8b09)
Solutions
- Unwrap the Base error to see the last attempt's actual failure (dial vs non-200 vs TLS)
- Test the proxy by hand: `curl -x http://user:pass@proxy:3128 https://target -v`
- Fix credentials/allowlist/port policy on the proxy side
- If non-200, check the proxy's response code — 407 means auth, 403 means policy
Defensive patterns
Strategy: retry
Validate before calling
```go
// one-shot probe before trusting the outbound
if err := probeHTTPTunnel(ctx, proxyDest, user, dialer); err != nil {
// surface proxy misconfig early instead of 5 blind retries
}
``` Try / catch
```go
if err := c.Process(ctx, link, dialer); err != nil {
if strings.Contains(err.Error(), "failed to find an available destination") {
base := errors.Unwrap(err) // last retry's cause: dial / non-200 / TLS
// only retry on transient dial errors; fix auth/ACL otherwise
}
}
``` Prevention
- curl-test proxies before adding them to config
- Keep credentials in sync with the proxy
- Watch for stale cached h2 connections after proxy restarts
When it happens
Trigger: HTTP proxy server down/unreachable, CONNECT rejected with non-200 (auth failure, forbidden target), TLS handshake failure when TLS is in play, or first-payload write after non-h2 CONNECT failing repeatedly. The 5-attempt backoff amplifies transient errors into a single final failure.
Common situations: Wrong credentials in settings.servers[].users, proxy requiring allowlisting the Xray host's IP, proxy that blocks CONNECT to non-443 ports, cached h2 conn going stale (CanTakeNewRequest false) forcing fresh failures.
Related errors
- Proxy responded with non 200 code: {status}
- cannot dial remote address
- failed to process outbound traffic
- unable to find an available mux client
- Proxy tag is not set.
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/29a1d23f987a9c9e.
Report an issue: GitHub.