gRPC streaming "Stream removed" (code 2) in CI
gRPC reports "Stream removed" when the underlying HTTP/2 stream is destroyed before the RPC finishes. It surfaces as a code 13 INTERNAL error and usually means the server dropped or reset the connection mid-stream.
What this error means
A streaming RPC test fails with "Error: 13 INTERNAL: Stream removed". It is intermittent, appearing when the server restarts, a proxy resets the connection, or the stream is closed early.
Error: 13 INTERNAL: Stream removed
at Object.callErrorFromStatus (node_modules/@grpc/grpc-js/build/src/call.js:...)
at Http2CallStream.<anonymous> (...)Common causes
The server closed the HTTP/2 connection mid-stream
A server restart or crash while a stream is active destroys the stream, which grpc-js reports as "Stream removed".
A proxy reset the long-lived stream
A load balancer or proxy that resets idle or long-running HTTP/2 streams tears down the stream before the RPC completes.
How to fix it
Keep the server stable and retry transient streams
- Ensure the gRPC server is not restarted while a streaming test is running.
- Handle the stream
errorevent so the failure is visible, not swallowed. - Retry the stream once on a transient INTERNAL/Stream removed.
stream.on('error', (err) => {
if (err.code === grpc.status.INTERNAL) retryOnce();
else done(err);
});Tune keep-alive so streams are not reset
Configure client keep-alive so long-lived streams stay healthy through proxies.
const client = new Service(addr, creds, {
'grpc.keepalive_time_ms': 10000,
'grpc.keepalive_timeout_ms': 5000,
});How to prevent it
- Do not restart the gRPC server while streaming tests run.
- Configure keep-alive for long-lived streams.
- Retry a single transient Stream removed in setup.