{"record":{"id":"4b387ba61b056b17","repo":"grpc/grpc-go","slug":"invalid-grpc-request-content-type-q","errorCode":null,"errorMessage":"invalid gRPC request content-type %q","messagePattern":"invalid gRPC request content-type %q","errorType":"http","errorClass":null,"httpStatus":415,"severity":"error","filePath":"internal/transport/handler_server.go","lineNumber":66,"sourceCode":")\n\n// NewServerHandlerTransport returns a ServerTransport handling gRPC from\n// inside an http.Handler, or writes an HTTP error to w and returns an error.\n// It requires that the http Server supports HTTP/2.\nfunc 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 {","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/transport/handler_server.go#L48-L84","documentation":"Returned by NewServerHandlerTransport when the request's Content-Type header is not a valid gRPC content type (application/grpc or application/grpc+<subtype>). The handler writes a 415 Unsupported Media Type and returns the error, see internal/transport/handler_server.go:60-66.","triggerScenarios":"Sending a request with a missing or wrong Content-Type (e.g. application/json, text/plain) to the gRPC http.Handler transport; a proxy stripping or rewriting the Content-Type header.","commonSituations":"Calling the endpoint with a plain HTTP/JSON client instead of a gRPC client; grpc-web transcoding gateway not setting Content-Type; a service mesh mutating headers; forgetting Content-Type in a manual curl.","solutions":["Send requests with Content-Type: application/grpc (or application/grpc+proto) from a real gRPC client.","Fix proxy/gateway config to preserve the original Content-Type header end-to-end.","For grpc-web, ensure the gateway translates the content type correctly before forwarding.","Verify with curl: curl -X POST -H 'Content-Type: application/grpc' ..."],"exampleFix":"// before\ncurl http://svc/Service/Method -H 'Content-Type: application/json'\n\n// after\ncurl http://svc/Service/Method --http2-prior-knowledge \\\n  -H 'Content-Type: application/grpc' -H 'TE: trailers'","handlingStrategy":"validation","validationCode":"ct := r.Header.Get(\"Content-Type\")\nif _, ok := grpcutil.ContentSubtype(ct); !ok {\n    http.Error(w, \"expect application/grpc\", http.StatusUnsupportedMediaType)\n    return\n}","typeGuard":"func isGRPCContentType(ct string) bool { _, ok := grpcutil.ContentSubtype(ct); return ok }","tryCatchPattern":"if _, err := transport.NewServerHandlerTransport(w, r, stats, pool); err != nil {\n    log.Printf(\"rejected non-gRPC request: %v\", err)\n}","preventionTips":["Always use a gRPC client which sets Content-Type: application/grpc.","Preserve the Content-Type header through every proxy/gateway hop.","Reject requests with unexpected content types at the edge."],"tags":["go","grpc","transport","http","content-type"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}