{"record":{"id":"a990babff043e323","repo":"XTLS/Xray-core","slug":"udp-is-not-supported-by-http-outbound","errorCode":null,"errorMessage":"UDP is not supported by HTTP outbound","messagePattern":"UDP is not supported by HTTP outbound","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"proxy/http/client.go","lineNumber":81,"sourceCode":"\t\tpolicyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),\n\t\theader:        config.Header,\n\t}, nil\n}\n\n// Process implements proxy.Outbound.Process. We first create a socket tunnel via HTTP CONNECT method, then redirect all inbound traffic to that tunnel.\nfunc (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {\n\toutbounds := session.OutboundsFromContext(ctx)\n\tob := outbounds[len(outbounds)-1]\n\tif !ob.Target.IsValid() {\n\t\treturn errors.New(\"target not specified.\")\n\t}\n\tob.Name = \"http\"\n\tob.CanSpliceCopy = 2\n\ttarget := ob.Target\n\ttargetAddr := target.NetAddr()\n\n\tif target.Network == net.Network_UDP {\n\t\treturn errors.New(\"UDP is not supported by HTTP outbound\")\n\t}\n\n\tserver := c.server\n\tdest := server.Destination\n\tuser := server.User\n\tvar conn stat.Connection\n\n\tmbuf, _ := link.Reader.ReadMultiBuffer()\n\tlen := mbuf.Len()\n\tfirstPayload := bytespool.Alloc(len)\n\tmbuf, _ = buf.SplitBytes(mbuf, firstPayload)\n\tfirstPayload = firstPayload[:len]\n\n\tbuf.ReleaseMulti(mbuf)\n\tdefer bytespool.Free(firstPayload)\n\n\theader, err := fillRequestHeader(ctx, c.header)\n\tif err != nil {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/http/client.go#L63-L99","documentation":"The HTTP outbound only implements HTTP CONNECT, which is a TCP-tunnel mechanism; a session with Network == UDP cannot be carried. The handler rejects UDP targets outright instead of attempting a bogus CONNECT.","triggerScenarios":"A UDP flow (DNS, QUIC, WireGuard, voice) is routed to an outbound with \"protocol\":\"http\". Typical triggers: browser QUIC/HTTP3 traffic (UDP 443) matching the default route, or DNS leaked into the proxy chain.","commonSituations":"Clients with HTTP3/QUIC enabled behind an HTTP-only outbound; routing rules with network field unset (defaults to tcp+udp) pointing at the HTTP outbound.","solutions":["Route UDP elsewhere: point UDP traffic at a SOCKS5u/freedom outbound via a routing rule with \"network\": \"udp\"","Or restrict the HTTP outbound's routing rule to \"network\": \"tcp\"","Alternatively block QUIC (drop udp:443) so browsers fall back to TCP/H2"],"exampleFix":"// routing.json — send udp elsewhere\n{ \"type\": \"field\", \"network\": \"udp\", \"outboundTag\": \"direct-udp\" }","handlingStrategy":"validation","validationCode":"```go\nif target.Network == net.Network_UDP {\n    // dispatch to a UDP-capable outbound (socks5u/freedom) instead\n}\n```","typeGuard":"```go\nfunc isUDPSession(target net.Destination) bool {\n    return target.Network == net.Network_UDP\n}\n```","tryCatchPattern":null,"preventionTips":["Pin routing rules for the http outbound to network tcp","Block or redirect udp/443 to stop QUIC reaching it","Prefer freedom/socks for mixed-protocol routes"],"tags":["http-outbound","udp","quic","routing","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}