gRPC "PROTOCOL_ERROR" over HTTP/2 in CI
gRPC runs over HTTP/2. A PROTOCOL_ERROR (RST_STREAM code 1) means the peer rejected the stream at the HTTP/2 layer: typically the target is not a real gRPC server, or a proxy/load balancer between them does not speak HTTP/2 end to end.
What this error means
A call fails with "14 UNAVAILABLE: ... Received RST_STREAM with code 1 (PROTOCOL_ERROR)" or "stream terminated by RST_STREAM with error code: PROTOCOL_ERROR", often through an ingress or proxy.
Error: 14 UNAVAILABLE: Received RST_STREAM with code 1 (PROTOCOL_ERROR)
at Object.callErrorFromStatus (.../call.js)Common causes
The target is not a gRPC/HTTP/2 server
The client connected to an HTTP/1.1 endpoint or a wrong port, so the HTTP/2 frames the server returns are rejected as a protocol error.
A proxy that does not preserve HTTP/2
A load balancer or ingress terminates or downgrades HTTP/2, breaking the end-to-end protocol gRPC requires.
How to fix it
Point the client at a real gRPC endpoint
- Confirm the target port serves gRPC (HTTP/2), not an HTTP/1.1 app.
- If a proxy sits in between, configure it for end-to-end HTTP/2 (h2c or gRPC mode).
- Verify with grpcurl against the same address.
grpcurl -plaintext localhost:50051 list # confirms it speaks gRPCEnable HTTP/2 through the proxy
Set the proxy/ingress backend protocol to gRPC or HTTP/2 so frames are not downgraded.
# nginx ingress: backend must speak gRPC end to end
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"How to prevent it
- Connect only to ports that serve gRPC over HTTP/2.
- Configure proxies and ingress for end-to-end HTTP/2.
- Smoke-test the endpoint with grpcurl before the suite.