{"record":{"id":"ad6ae533d4035650","repo":"chenhg5/cc-connect","slug":"googlechat-close-attachment-create-response-body","errorCode":null,"errorMessage":"googlechat: close attachment create response body: %w","messagePattern":"googlechat: close attachment create response body: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"platform/googlechat/googlechat.go","lineNumber":554,"sourceCode":"\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)\n}\n\n// SendFile uploads a file and posts it as a Chat message attachment.","sourceCodeStart":536,"sourceCodeEnd":572,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/googlechat/googlechat.go#L536-L572","documentation":"Closing the HTTP response body of the attachment-create call returned an error. Go's http.Response.Body.Close can fail when the connection could not be reused or the underlying read failed; the platform surfaces it rather than ignoring it.","triggerScenarios":"resp.Body.Close() returns non-nil after a successful attachment-create POST — typically due to a broken underlying connection or an error on a wrapped body (e.g. compressed responses failing to finalize).","commonSituations":"Keep-alive connection teardown races; HTTP/2 stream reset after the payload was already consumed; proxy interference. The send itself usually succeeded.","solutions":["Treat as non-fatal if the message was confirmed sent — log and continue","Verify no proxy/middlebox is resetting connections to chat.googleapis.com","Retry only if delivery is genuinely uncertain"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := p.SendFile(ctx, rc, file); err != nil {\n    if strings.Contains(err.Error(), \"close attachment create response body\") {\n        slog.Warn(\"googlechat: body close failed; send likely succeeded\", \"error\", err)\n        return nil\n    }\n    return err\n}","preventionTips":["Treat body-close errors as non-fatal when delivery succeeded","Watch for proxies resetting keep-alive connections","Keep HTTP client and TLS stack updated"],"tags":["googlechat","http","resource-cleanup"],"backgroundTag":"broken-pipe","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}