{"record":{"id":"5dd28f26418e3104","repo":"XTLS/Xray-core","slug":"failed-to-find-an-available-destination-5dd28f","errorCode":null,"errorMessage":"failed to find an available destination","messagePattern":"failed to find an available destination","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"proxy/trojan/client.go","lineNumber":72,"sourceCode":"\tob.Name = \"trojan\"\n\tob.CanSpliceCopy = 3\n\tdestination := ob.Target\n\tnetwork := destination.Network\n\n\tserver := c.server\n\tvar conn stat.Connection\n\n\terr := retry.ExponentialBackoff(5, 100).On(func() error {\n\t\trawConn, err := dialer.Dial(ctx, server.Destination)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tconn = rawConn\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn errors.New(\"failed to find an available destination\").AtWarning().Base(err)\n\t}\n\terrors.LogInfo(ctx, \"tunneling request to \", destination, \" via \", server.Destination.NetAddr())\n\n\tdefer conn.Close()\n\n\tuser := server.User\n\taccount, ok := user.Account.(*MemoryAccount)\n\tif !ok {\n\t\treturn errors.New(\"user account is not valid\")\n\t}\n\n\tvar newCtx context.Context\n\tvar newCancel context.CancelFunc\n\tif session.TimeoutOnlyFromContext(ctx) {\n\t\tnewCtx, newCancel = context.WithCancel(context.Background())\n\t}\n\n\tsessionPolicy := c.policyManager.ForLevel(user.Level)","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/trojan/client.go#L54-L90","documentation":"Thrown when the trojan client's retry loop (ExponentialBackoff 5 attempts starting at 100ms) fails on every dial to server.Destination. It wraps the last dial error and is marked AtWarning: the tunnel cannot be established at all, and after ~3s of retries the request fails.","triggerScenarios":"dialer.Dial(ctx, server.Destination) failing 5 consecutive times: connection refused/timeout, TLS handshake failure to the trojan server, DNS resolution failure of the server address, or the server port blocked.","commonSituations":"Trojan server down or moved; wrong address/port in outbound; SNI/serverName mismatch causing TLS failure; GFW/firewall blocking the server IP; DNS for the server domain poisoned or expired.","solutions":["Check the Base error: dial tcp ... i/o timeout vs TLS errors point to network vs certificate problems.","Verify the trojan server is up and the port open (nc -vz host port, openssl s_client -connect host:port).","Confirm outbound address/port/password and streamSettings (TLS serverName) match the server exactly.","If the IP is blocked, switch to a new server address or use a CDN-fronted transport.","Fix DNS: ensure the server domain resolves (try domainStrategy UseIPv4 or a reliable DNS server in config)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight reachability before committing the tunnel\nif err := probeTCP(server.Destination.NetAddr(), 3*time.Second); err != nil {\n\treturn errors.New(\"trojan server unreachable: \").Base(err)\n}","typeGuard":null,"tryCatchPattern":"if err := client.Process(ctx, link, dialer); err != nil {\n\tif strings.Contains(err.Error(), \"failed to find an available destination\") {\n\t\tbackoff.Retry(...) // or switch to the backup server in the config\n\t}\n}","preventionTips":["Keep a backup trojan server entry and rotate on dial failure.","Monitor server reachability externally (synthetic dial checks).","Verify TLS serverName matches the certificate to avoid handshake-level dial failures."],"tags":["trojan","outbound","dial","retry","connectivity"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}