{"record":{"id":"45655b4eba47ac19","repo":"grpc/grpc-go","slug":"grpc-requires-http-2","errorCode":null,"errorMessage":"gRPC requires HTTP/2","messagePattern":"gRPC requires HTTP/2","errorType":"http","errorClass":null,"httpStatus":505,"severity":"error","filePath":"internal/transport/handler_server.go","lineNumber":71,"sourceCode":"func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats stats.Handler, bufferPool mem.BufferPool) (ServerTransport, error) {\n\tif r.Method != http.MethodPost {\n\t\tw.Header().Set(\"Allow\", http.MethodPost)\n\t\tmsg := fmt.Sprintf(\"invalid gRPC request method %q\", r.Method)\n\t\thttp.Error(w, msg, http.StatusMethodNotAllowed)\n\t\treturn nil, errors.New(msg)\n\t}\n\tcontentType := r.Header.Get(\"Content-Type\")\n\t// TODO: do we assume contentType is lowercase? we did before\n\tcontentSubtype, validContentType := grpcutil.ContentSubtype(contentType)\n\tif !validContentType {\n\t\tmsg := fmt.Sprintf(\"invalid gRPC request content-type %q\", contentType)\n\t\thttp.Error(w, msg, http.StatusUnsupportedMediaType)\n\t\treturn nil, errors.New(msg)\n\t}\n\tif r.ProtoMajor != 2 {\n\t\tmsg := \"gRPC requires HTTP/2\"\n\t\thttp.Error(w, msg, http.StatusHTTPVersionNotSupported)\n\t\treturn nil, errors.New(msg)\n\t}\n\tif _, ok := w.(http.Flusher); !ok {\n\t\tmsg := \"gRPC requires a ResponseWriter supporting http.Flusher\"\n\t\thttp.Error(w, msg, http.StatusInternalServerError)\n\t\treturn nil, errors.New(msg)\n\t}\n\n\tvar localAddr net.Addr\n\tif la := r.Context().Value(http.LocalAddrContextKey); la != nil {\n\t\tlocalAddr, _ = la.(net.Addr)\n\t}\n\tvar authInfo credentials.AuthInfo\n\tif r.TLS != nil {\n\t\tauthInfo = credentials.TLSInfo{State: *r.TLS, CommonAuthInfo: credentials.CommonAuthInfo{SecurityLevel: credentials.PrivacyAndIntegrity}}\n\t}\n\tp := peer.Peer{\n\t\tAddr:      strAddr(r.RemoteAddr),\n\t\tLocalAddr: localAddr,","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/transport/handler_server.go#L53-L89","documentation":"Returned by NewServerHandlerTransport when r.ProtoMajor is not 2. gRPC is built on HTTP/2 and cannot function over HTTP/1.1 because it relies on HTTP/2 multiplexing, streaming, and trailers. The transport rejects the request with HTTP 505 HTTP Version Not Supported. This only affects the handler-server (net/http integration) transport path.","triggerScenarios":"An HTTP/1.1 request reaches the gRPC handler transport. This happens when the net/http server is not configured for HTTP/2 (no TLS, or TLS without h2 ALPN, or h2c not enabled for cleartext), so the request arrives as HTTP/1.1.","commonSituations":"Running gRPC handler on plain HTTP without h2c; TLS server without ALPN negotiation for h2; using http.ListenAndServe (HTTP/1.1 only) instead of http2-compatible setup; client connecting via HTTP/1.1 proxy that doesn't upgrade.","solutions":["Enable HTTP/2 on your net/http server: use TLS with ALPN ('h2') via http.ServeTLS, or enable h2c for cleartext via golang.org/x/net/http2/h2c.","Ensure the TLS certificate and server config advertise h2 in NextProtos.","For cleartext (no TLS), wrap the handler with h2c.NewHandler.","Verify clients and proxies are HTTP/2 capable."],"exampleFix":"// before: HTTP/1.1 only\nhttp.ListenAndServe(\":8080\", grpcHandler)\n// after: enable h2c for cleartext HTTP/2\nimport \"golang.org/x/net/http2/h2c\"\nh2s := &http.Server{Handler: h2c.NewHandler(grpcHandler, &http2.Server{})}\nh2s.ListenAndServe()\n\n// or with TLS + ALPN:\nhttp.ListenAndServeTLS(\":443\", \"cert.pem\", \"key.pem\", grpcHandler)","handlingStrategy":"validation","validationCode":"// Ensure the HTTP server supports HTTP/2 before serving gRPC.\n// With TLS: use http.ServeTLS with ALPN h2.\n// Without TLS: use h2c.NewHandler.\nimport \"golang.org/x/net/http2/h2c\"\nh2s := &http.Server{\n    Handler: h2c.NewHandler(grpcServer, &http2.Server{}),\n}\nh2s.ListenAndServe()","typeGuard":null,"tryCatchPattern":"st, err := transport.NewServerHandlerTransport(w, r, stats, pool)\nif err != nil {\n    if strings.Contains(err.Error(), \"requires HTTP/2\") {\n        log.Fatal(\"server must use HTTP/2; enable h2c or TLS+ALPN\")\n    }\n}","preventionTips":["Enable HTTP/2 on your net/http server (TLS+ALPN for h2, or h2c for cleartext).","Test with HTTP/2-capable clients (standard gRPC clients use HTTP/2).","Verify load balancers and proxies support and negotiate HTTP/2.","Do not use plain http.ListenAndServe for gRPC handler transports."],"tags":["transport","http2","handler-server","grpc","network"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}