{"record":{"id":"caa0eed8e4bf3263","repo":"XTLS/Xray-core","slug":"negotiated-unsupported-application-layer-protocol","errorCode":null,"errorMessage":"negotiated unsupported application layer protocol: {nextProto}","messagePattern":"negotiated unsupported application layer protocol: (.+?)","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"proxy/http/client.go","lineNumber":348,"sourceCode":"\t\tif err != nil {\n\t\t\trawConn.Close()\n\t\t\treturn nil, err\n\t\t}\n\n\t\tcachedH2Mutex.Lock()\n\t\tif cachedH2Conns == nil {\n\t\t\tcachedH2Conns = make(map[net.Destination]h2Conn)\n\t\t}\n\n\t\tcachedH2Conns[dest] = h2Conn{\n\t\t\trawConn: rawConn,\n\t\t\th2Conn:  h2clientConn,\n\t\t}\n\t\tcachedH2Mutex.Unlock()\n\n\t\treturn proxyConn, err\n\tdefault:\n\t\treturn nil, errors.New(\"negotiated unsupported application layer protocol: \" + nextProto)\n\t}\n}\n\nfunc newHTTP2Conn(c net.Conn, pipedReqBody *io.PipeWriter, respBody io.ReadCloser) net.Conn {\n\treturn &http2Conn{Conn: c, in: pipedReqBody, out: respBody}\n}\n\ntype http2Conn struct {\n\tnet.Conn\n\tin  *io.PipeWriter\n\tout io.ReadCloser\n}\n\nfunc (h *http2Conn) Read(p []byte) (n int, err error) {\n\treturn h.out.Read(p)\n}\n\nfunc (h *http2Conn) Write(p []byte) (n int, err error) {","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/http/client.go#L330-L366","documentation":"After establishing the transport to the HTTP proxy, the client switches on the negotiated ALPN nextProto. Only \"h2\" and \"\"/\"http/1.1\" are handled; any other negotiated protocol (e.g. \"h3\", experimental strings from a TLS-terminating middlebox) falls into default and this error is returned.","triggerScenarios":"settings.servers[].tls enabled (or stream TLS to the proxy) where the TLS endpoint negotiates something other than h2 or http/1.1 — custom ALPN lists in streamSettings.tlsSettings.alpn, h3-capable proxies, or an intercepting box injecting unexpected protocols.","commonSituations":"User sets tlsSettings.alpn to [\"h3\"] or [\"h2\",\"h3\"] for an HTTP outbound; a CDN/LB in front of the proxy negotiating its preferred proto; older Xray builds without some proto support.","solutions":["Restrict streamSettings.tlsSettings.alpn to [\"h2\", \"http/1.1\"] for the HTTP outbound","Ensure you are actually talking to the HTTP proxy, not a CDN endpoint that negotiates other protocols","Upgrade Xray if a newer build supports additional protocols on this path","Check for TLS-intercepting middleboxes rewriting ALPN"],"exampleFix":"// before\n\"streamSettings\": { \"tlsSettings\": { \"alpn\": [\"h3\"] } }\n// after\n\"streamSettings\": { \"tlsSettings\": { \"alpn\": [\"h2\", \"http/1.1\"] } }","handlingStrategy":"validation","validationCode":"```go\nallowed := map[string]bool{\"h2\": true, \"http/1.1\": true, \"\": true}\nif state, ok := tls ConnectionState(); ok && !allowed[state.NegotiatedProtocol] {\n    // fix alpn config before the outbound trips the default case\n}\n```","typeGuard":"```go\nfunc supportedALPN(proto string) bool {\n    return proto == \"\" || proto == \"h2\" || proto == \"http/1.1\"\n}\n```","tryCatchPattern":null,"preventionTips":["Pin tlsSettings.alpn to [\"h2\",\"http/1.1\"] for HTTP outbounds","Point the outbound directly at the proxy, not a CDN edge","Re-check ALPN config after upgrades"],"tags":["http-outbound","alpn","tls","http2","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}