{
  "id": "grpc/grpc-client-side-stream-abort",
  "signature": "CANCELLED: grpc: client-side stream aborted by client",
  "signature_zh": "已取消: grpc: 客户端侧流被客户端中止",
  "regex": "CANCELLED: grpc: client-side stream aborted by client",
  "domain": "grpc",
  "category": "runtime_error",
  "subcategory": null,
  "root_cause": "Client explicitly closed or cancelled the stream before the server finished processing, often due to premature context cancellation or stream.CloseSend() misuse.",
  "root_cause_type": "generic",
  "root_cause_zh": "客户端在服务器完成处理之前显式关闭或取消了流，通常是由于过早的上下文取消或 stream.CloseSend() 的误用。",
  "versions": [
    {
      "version": "grpc-go 1.62.0",
      "introduced": null,
      "deprecated": null,
      "removed": null,
      "behavior_change": null,
      "status": "active"
    },
    {
      "version": "grpc-python 1.60.0",
      "introduced": null,
      "deprecated": null,
      "removed": null,
      "behavior_change": null,
      "status": "active"
    },
    {
      "version": "grpc-node 1.10.0",
      "introduced": null,
      "deprecated": null,
      "removed": null,
      "behavior_change": null,
      "status": "active"
    }
  ],
  "os_specific": {},
  "dead_ends": [
    {
      "action": "",
      "why_fails": "The error is caused by explicit cancellation or stream abort, not timeout; extending timeout doesn't prevent premature CloseSend().",
      "fail_rate": 0.8,
      "condition": "",
      "sources": []
    },
    {
      "action": "",
      "why_fails": "The stream is already closed; server cannot send responses, leading to resource leaks and inconsistent state.",
      "fail_rate": 0.95,
      "condition": "",
      "sources": []
    }
  ],
  "workarounds": [
    {
      "action": "Ensure the client does not call stream.CloseSend() before receiving all server responses. In gRPC-Go, use a proper pattern:\n  stream, err := client.StreamingMethod(ctx)\n  // Send all messages\n  stream.CloseSend()\n  // Then receive all responses\n  for {\n      resp, err := stream.Recv()\n      if err == io.EOF { break }\n  }",
      "success_rate": 0.9,
      "how": "Ensure the client does not call stream.CloseSend() before receiving all server responses. In gRPC-Go, use a proper pattern:\n  stream, err := client.StreamingMethod(ctx)\n  // Send all messages\n  stream.CloseSend()\n  // Then receive all responses\n  for {\n      resp, err := stream.Recv()\n      if err == io.EOF { break }\n  }",
      "condition": "",
      "sources": []
    },
    {
      "action": "Add a defer cancel() after creating the context to ensure proper cleanup without premature cancellation:\n  ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n  defer cancel()\n  stream, _ := client.StreamingMethod(ctx)\n  // Use stream\n  // cancel() will be called when function returns, not before stream completes",
      "success_rate": 0.8,
      "how": "Add a defer cancel() after creating the context to ensure proper cleanup without premature cancellation:\n  ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n  defer cancel()\n  stream, _ := client.StreamingMethod(ctx)\n  // Use stream\n  // cancel() will be called when function returns, not before stream completes",
      "condition": "",
      "sources": []
    }
  ],
  "workarounds_zh": [
    "Ensure the client does not call stream.CloseSend() before receiving all server responses. In gRPC-Go, use a proper pattern:\n  stream, err := client.StreamingMethod(ctx)\n  // Send all messages\n  stream.CloseSend()\n  // Then receive all responses\n  for {\n      resp, err := stream.Recv()\n      if err == io.EOF { break }\n  }",
    "Add a defer cancel() after creating the context to ensure proper cleanup without premature cancellation:\n  ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n  defer cancel()\n  stream, _ := client.StreamingMethod(ctx)\n  // Use stream\n  // cancel() will be called when function returns, not before stream completes"
  ],
  "transition_graph": {
    "leads_to": [],
    "preceded_by": [],
    "frequently_confused_with": []
  },
  "official_doc_url": "https://grpc.io/docs/languages/go/basics/#client-side-streaming-rpc",
  "official_doc_section": null,
  "error_code": null,
  "verification_tier": "ai_generated",
  "confidence": 0.82,
  "fix_success_rate": 0.85,
  "resolvable": "true",
  "first_seen": "2024-01-10",
  "last_confirmed": "2024-06-01",
  "last_updated": "2024-06-01",
  "evidence_count": 1,
  "tags": [],
  "locale": "en",
  "aliases": []
}