{"record":{"id":"8ac55779d878a50f","repo":"chenhg5/cc-connect","slug":"googlechat-drain-attachment-create-response-body","errorCode":null,"errorMessage":"googlechat: drain attachment create response body: %w","messagePattern":"googlechat: drain attachment create response body: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"platform/googlechat/googlechat.go","lineNumber":551,"sourceCode":"\tif err != nil {\n\t\treturn err\n\t}\n\turl, body, err := buildAttachmentRequest(rc, resourceName)\n\tif err != nil {\n\t\treturn err\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"googlechat: attachment message: build request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\tresp, err := p.doRequest(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif _, err := io.Copy(io.Discard, resp.Body); err != nil {\n\t\t_ = resp.Body.Close()\n\t\treturn fmt.Errorf(\"googlechat: drain attachment create response body: %w\", err)\n\t}\n\tif err := resp.Body.Close(); err != nil {\n\t\treturn fmt.Errorf(\"googlechat: close attachment create response body: %w\", err)\n\t}\n\treturn nil\n}\n\n// SendImage uploads an image and posts it as a Chat message attachment.\n// Implements core.ImageSender.\nfunc (p *Platform) SendImage(ctx context.Context, rctx any, img core.ImageAttachment) error {\n\trc, ok := rctx.(replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"googlechat: SendImage: invalid reply context type %T\", rctx)\n\t}\n\treturn p.postAttachment(ctx, rc,\n\t\tcoalesce(img.FileName, \"image.png\"),\n\t\tcoalesce(img.MimeType, \"image/png\"),\n\t\timg.Data)","sourceCodeStart":533,"sourceCodeEnd":569,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/googlechat/googlechat.go#L533-L569","documentation":"After the attachment-create POST succeeds at the transport level, the platform drains the response body with io.Copy(io.Discard, ...). If reading the body fails (connection reset mid-response, context cancellation, TLS error), the body is closed and this wrapped error is returned.","triggerScenarios":"The Google Chat API connection drops while the response body is still being read; the request context is cancelled between receiving headers and draining the body.","commonSituations":"Unstable networks or proxies closing keep-alive connections early; callers cancelling the context during a slow upload; corporate proxies truncating responses.","solutions":["Retry the postAttachment call — the error is transient network-level","Check proxy/firewall stability between the host and chat.googleapis.com","Avoid cancelling the context while attachment sends are in flight"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := p.SendImage(ctx, rc, img); err != nil {\n    if isTransientNetwork(err) { return retryWithBackoff(ctx, 3, func() error { return p.SendImage(ctx, rc, img) }) }\n    return err\n}","preventionTips":["Ensure stable egress to chat.googleapis.com","Avoid cancelling contexts mid-upload","Monitor proxy keep-alive behavior"],"tags":["googlechat","network","http"],"backgroundTag":"network-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}