# INTERNAL: grpc: flow control window exhausted for stream 123

- **ID:** `grpc/flow-control-window-exhausted`
- **Domain:** grpc
- **Category:** resource_error
- **Error Code:** `EFLOWCTRL`
- **Verification:** ai_generated
- **Fix Rate:** 75%

## Root Cause

The HTTP/2 flow control window for a specific stream is exhausted because the receiver is not consuming data fast enough, leading to a stall or internal error.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| gRPC v1.56.0 | active | — | — |
| gRPC v1.60.0 | active | — | — |
| gRPC v1.63.0 | active | — | — |

## Workarounds

1. **Increase the initial flow control window size on the server: `server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), options=[('grpc.initial_reconnect_backoff_ms', 1000), ('grpc.http2.min_recv_flow_control_window', 8388608)])`** (85% success)
   ```
   Increase the initial flow control window size on the server: `server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), options=[('grpc.initial_reconnect_backoff_ms', 1000), ('grpc.http2.min_recv_flow_control_window', 8388608)])`
   ```
2. **Optimize the receiver's data consumption by batching reads or using async I/O to avoid blocking the event loop.** (80% success)
   ```
   Optimize the receiver's data consumption by batching reads or using async I/O to avoid blocking the event loop.
   ```
3. **Implement backpressure at the application layer: have the client send smaller chunks or wait for acknowledgments before sending more data.** (75% success)
   ```
   Implement backpressure at the application layer: have the client send smaller chunks or wait for acknowledgments before sending more data.
   ```

## Dead Ends

- **Restarting the client or server without changing flow control settings.** — The window exhaustion recurs under the same load pattern; restarting only provides temporary relief. (80% fail)
- **Disabling flow control entirely by setting `grpc.http2.lookahead_bytes` to 0.** — Flow control is a fundamental HTTP/2 mechanism; disabling it can cause memory exhaustion and connection instability. (70% fail)
- **Increasing the number of worker threads on the receiver side.** — While it may help consume data faster, the root cause is often slow application-level processing, not thread count. (50% fail)
