Skip to content
Latchkey

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.

gRPC
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

  1. Ensure the gRPC server is not restarted while a streaming test is running.
  2. Handle the stream error event so the failure is visible, not swallowed.
  3. Retry the stream once on a transient INTERNAL/Stream removed.
test.mjs
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.

test.mjs
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.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →