client must not attempt decode responses with wrong content type
Bug Report
When non-gRPC error is returned, for example 502 bad gateway by a proxy server, tonic client returns an error like
status: Internal, message: "protocol error: received message with invalid compression flag: 60 (valid flags are 0 and 1) while receiving response with status: 502 Bad Gateway", details: [], metadata: MetadataMap { headers: {"date": "Fri, 01 Aug 2025 02:23:45 GMT", "content-type": "text/html", "content-length": "150", "strict-transport-security": "max-age=31536000; includeSubDomains"} }
Content-type is not application/grpc, so attempt to read first byte as either 0 or 1 for compression is incorrect.
Version
0.13
Error comes from here:
https://github.com/hyperium/tonic/blob/87d2d4c5055eae231318bab6c8c94fbd466a7750/tonic/src/codec/decode.rs#L176
@dfawley I assume the current implementation is incorrect, do you have an idea of what grpc-go does in this case?
When the headers indicate the wrong content-type encoding, the stream will be closed immediately (with a RST_STREAM if the server didn't already include an END_STREAM on its headers frame). Locally, the application will see an INTERNAL error code, unless the HTTP status was not 200, in which case we'll do that conversion instead:
https://github.com/grpc/grpc-go/blob/85240a5b02defe7b653ccba66866b4370c982b6a/internal/transport/http2_client.go#L1481-L1485
https://github.com/grpc/grpc-go/blob/85240a5b02defe7b653ccba66866b4370c982b6a/internal/transport/http2_client.go#L1551-L1556
Apparently Go isn't handling 1xx statuses in HEADERS frames correctly (unless the framer we're using hides them, which I would doubt). I believe we'll error instead of ignoring them. (https://github.com/grpc/grpc-go/issues/8485)
Also, apparently Java has some interesting logic to help users with debugging in this case. It will read data frames (if the headers don't include END_STREAM) up to 1kb, and includes that in the status message. (https://github.com/grpc/grpc-go/issues/8487)
And lastly, per @ejona86, if the content-type is grpc, then we should not be inspecting the status, which Go is also doing incorrectly. (https://github.com/grpc/grpc-go/issues/8486)
EDIT: added issue links for all the problems I found with gRPC-Go.