grpc/grpc-go · error
invalid gRPC request content-type %q
Error message
invalid gRPC request content-type %q
What it means
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.
Source
Thrown at internal/transport/handler_server.go:66
)
// NewServerHandlerTransport returns a ServerTransport handling gRPC from
// inside an http.Handler, or writes an HTTP error to w and returns an error.
// It requires that the http Server supports HTTP/2.
func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats stats.Handler, bufferPool mem.BufferPool) (ServerTransport, error) {
if r.Method != http.MethodPost {
w.Header().Set("Allow", http.MethodPost)
msg := fmt.Sprintf("invalid gRPC request method %q", r.Method)
http.Error(w, msg, http.StatusMethodNotAllowed)
return nil, errors.New(msg)
}
contentType := r.Header.Get("Content-Type")
// TODO: do we assume contentType is lowercase? we did before
contentSubtype, validContentType := grpcutil.ContentSubtype(contentType)
if !validContentType {
msg := fmt.Sprintf("invalid gRPC request content-type %q", contentType)
http.Error(w, msg, http.StatusUnsupportedMediaType)
return nil, errors.New(msg)
}
if r.ProtoMajor != 2 {
msg := "gRPC requires HTTP/2"
http.Error(w, msg, http.StatusHTTPVersionNotSupported)
return nil, errors.New(msg)
}
if _, ok := w.(http.Flusher); !ok {
msg := "gRPC requires a ResponseWriter supporting http.Flusher"
http.Error(w, msg, http.StatusInternalServerError)
return nil, errors.New(msg)
}
var localAddr net.Addr
if la := r.Context().Value(http.LocalAddrContextKey); la != nil {
localAddr, _ = la.(net.Addr)
}
var authInfo credentials.AuthInfo
if r.TLS != nil {View on GitHub (pinned to 03255a9237)
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' ...
Example fix
// before curl http://svc/Service/Method -H 'Content-Type: application/json' // after curl http://svc/Service/Method --http2-prior-knowledge \ -H 'Content-Type: application/grpc' -H 'TE: trailers'
Defensive patterns
Strategy: validation
Validate before calling
ct := r.Header.Get("Content-Type")
if _, ok := grpcutil.ContentSubtype(ct); !ok {
http.Error(w, "expect application/grpc", http.StatusUnsupportedMediaType)
return
} Type guard
func isGRPCContentType(ct string) bool { _, ok := grpcutil.ContentSubtype(ct); return ok } Try / catch
if _, err := transport.NewServerHandlerTransport(w, r, stats, pool); err != nil {
log.Printf("rejected non-gRPC request: %v", err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- invalid gRPC request method %q
- token file access error
- empty token_exchange_service_uri in options
- required field SubjectTokenPath is not specified
- required field SubjectTokenType is not specified
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/4b387ba61b056b17.
Report an issue: GitHub.