# CANCELLED: grpc: client-side stream aborted by client

- **ID:** `grpc/grpc-client-side-stream-abort`
- **Domain:** grpc
- **Category:** runtime_error
- **Verification:** ai_generated
- **Fix Rate:** 85%

## Root Cause

Client explicitly closed or cancelled the stream before the server finished processing, often due to premature context cancellation or stream.CloseSend() misuse.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| grpc-go 1.62.0 | active | — | — |
| grpc-python 1.60.0 | active | — | — |
| grpc-node 1.10.0 | active | — | — |

## Workarounds

1. **Ensure the client does not call stream.CloseSend() before receiving all server responses. In gRPC-Go, use a proper pattern:
  stream, err := client.StreamingMethod(ctx)
  // Send all messages
  stream.CloseSend()
  // Then receive all responses
  for {
      resp, err := stream.Recv()
      if err == io.EOF { break }
  }** (90% success)
   ```
   Ensure the client does not call stream.CloseSend() before receiving all server responses. In gRPC-Go, use a proper pattern:
  stream, err := client.StreamingMethod(ctx)
  // Send all messages
  stream.CloseSend()
  // Then receive all responses
  for {
      resp, err := stream.Recv()
      if err == io.EOF { break }
  }
   ```
2. **Add a defer cancel() after creating the context to ensure proper cleanup without premature cancellation:
  ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  defer cancel()
  stream, _ := client.StreamingMethod(ctx)
  // Use stream
  // cancel() will be called when function returns, not before stream completes** (80% success)
   ```
   Add a defer cancel() after creating the context to ensure proper cleanup without premature cancellation:
  ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  defer cancel()
  stream, _ := client.StreamingMethod(ctx)
  // Use stream
  // cancel() will be called when function returns, not before stream completes
   ```

## Dead Ends

- **** — The error is caused by explicit cancellation or stream abort, not timeout; extending timeout doesn't prevent premature CloseSend(). (80% fail)
- **** — The stream is already closed; server cannot send responses, leading to resource leaks and inconsistent state. (95% fail)
