# gRPC client stream failed with RESOURCE_EXHAUSTED: Too many outstanding requests

- **ID:** `communication/grpc-client-stream-failed-with-resource-exhausted`
- **Domain:** communication
- **Category:** runtime_error
- **Error Code:** `RESOURCE_EXHAUSTED`
- **Verification:** ai_generated
- **Fix Rate:** 80%

## Root Cause

gRPC client-side flow control or concurrency limit exceeded, causing the channel to reject new streams.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| gRPC 1.54.0 | active | — | — |
| gRPC 1.60.0 | active | — | — |
| gRPC 1.62.0 | active | — | — |

## Workarounds

1. **Configure gRPC client channel with increased max_concurrent_streams and flow control window: In C++, set `ChannelArguments` with `GRPC_ARG_MAX_CONCURRENT_STREAMS` to 1000 and `GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE` to 64KB. In Python, use `grpc.insecure_channel(target, options=[('grpc.max_concurrent_streams', 1000)])`.** (85% success)
   ```
   Configure gRPC client channel with increased max_concurrent_streams and flow control window: In C++, set `ChannelArguments` with `GRPC_ARG_MAX_CONCURRENT_STREAMS` to 1000 and `GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE` to 64KB. In Python, use `grpc.insecure_channel(target, options=[('grpc.max_concurrent_streams', 1000)])`.
   ```
2. **Implement client-side rate limiting with a semaphore to limit in-flight requests: Use `asyncio.Semaphore(100)` in Python or `std::counting_semaphore` in C++ to throttle before sending.** (90% success)
   ```
   Implement client-side rate limiting with a semaphore to limit in-flight requests: Use `asyncio.Semaphore(100)` in Python or `std::counting_semaphore` in C++ to throttle before sending.
   ```
3. **Enable gRPC client-side keepalive with aggressive timeout to detect dead streams: Set `grpc.keepalive_time_ms` to 10000 and `grpc.keepalive_timeout_ms` to 5000.** (75% success)
   ```
   Enable gRPC client-side keepalive with aggressive timeout to detect dead streams: Set `grpc.keepalive_time_ms` to 10000 and `grpc.keepalive_timeout_ms` to 5000.
   ```

## Dead Ends

- **Increase the gRPC max concurrent streams on the server side only** — The issue is client-side concurrency limits; server-side changes don't help. (80% fail)
- **Restart the client process to reset channel state** — Restarting only temporarily clears the queue; the same condition recurs under load. (90% fail)
- **Ignore the error and retry indefinitely with backoff** — Without addressing the concurrency limit, retries will keep hitting the same error. (70% fail)
