{"record":{"id":"0319eedb9c72750f","repo":"XTLS/Xray-core","slug":"no-usable-outbound-interface-found","errorCode":null,"errorMessage":"no usable outbound interface found","messagePattern":"no usable outbound interface found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/tun/tun_linux.go","lineNumber":361,"sourceCode":"\t\t\treturn nil, err\n\t\t}\n\t\tif iface.Index == tunIndex {\n\t\t\treturn nil, errors.New(\"outbound interface cannot be the TUN interface\")\n\t\t}\n\t\treturn iface, nil\n\t}\n\n\tfor _, family := range []int{\n\t\tnetlink.FAMILY_V4,\n\t\tnetlink.FAMILY_V6,\n\t} {\n\t\tiface, err := findDefaultInterface(family, tunIndex)\n\t\tif err == nil {\n\t\t\treturn iface, nil\n\t\t}\n\t}\n\n\treturn nil, errors.New(\"no usable outbound interface found\")\n}\n\nfunc findDefaultInterface(family int, tunIndex int) (*net.Interface, error) {\n\troutes, err := netlink.RouteList(nil, family)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar selected *net.Interface\n\tselectedMetric := -1\n\n\tfor _, route := range routes {\n\t\tif route.Dst != nil {\n\t\t\tones, _ := route.Dst.Mask.Size()\n\t\t\tif ones != 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/tun/tun_linux.go#L343-L379","documentation":"With no fixed interface configured, Xray scans IPv4 then IPv6 route tables for a usable default-route interface that is not the TUN. If neither family yields a candidate, startup fails with this error. The machine effectively has no default route Xray can use to reach the internet.","triggerScenarios":"A VM/container with only a linked-scope or loopback setup; default route deleted; all default routes pointing at the just-created TUN; netlink route listing failing (permissions) so both family probes error.","commonSituations":"Minimal containers (docker default bridge removed), air-gapped test environments, misconfigured network namespaces, or a previous VPN client that replaced the default route and did not restore it.","solutions":["Restore a default route: `ip route add default via <gw> dev <phys>`","Configure the fixed outbound interface explicitly so auto-detection is skipped","In containers, run with a proper network stack (e.g. docker --network with a gateway)"],"exampleFix":"# before: no default route\nip route  # only link-scope routes\n\n# after\nip route add default via 192.168.1.1 dev eth0\n# then start xray","handlingStrategy":"validation","validationCode":"func hasDefaultRoute() bool {\n\tfor _, f := range []int{netlink.FAMILY_V4, netlink.FAMILY_V6} {\n\t\troutes, err := netlink.RouteList(nil, f)\n\t\tif err != nil { continue }\n\t\tfor _, r := range routes {\n\t\t\tif r.Dst == nil { return true }\n\t\t}\n\t}\n\treturn false\n}\n\nif !hasDefaultRoute() { log.Fatal(\"no default route; fix networking first\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify `ip route show default` exists before enabling tun mode","Pin the outbound interface to skip auto-detection","In containers, attach a network with a gateway"],"tags":["tun","linux","routing","default-route","environment"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}