chenhg5/cc-connect · warning
googlechat: drain response body: %w
Error message
googlechat: drain response body: %w
What it means
After a successful 2xx Chat API response, post drains the response body (io.Copy to io.Discard) so the HTTP connection can be reused, and wraps any drain failure with this error. It indicates the connection broke mid-read even though the request itself was accepted — the message was very likely delivered.
Source
Thrown at platform/googlechat/googlechat.go:436
if rc.space == "" {
return fmt.Errorf("googlechat: missing space in reply context")
}
url, body, err := buildSendRequest(rc, content)
if err != nil {
return err
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))
if err != nil {
return fmt.Errorf("googlechat: build request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := p.doRequest(req)
if err != nil {
return err
}
if _, err := io.Copy(io.Discard, resp.Body); err != nil {
_ = resp.Body.Close()
return fmt.Errorf("googlechat: drain response body: %w", err)
}
if err := resp.Body.Close(); err != nil {
return fmt.Errorf("googlechat: close response body: %w", err)
}
return nil
}
func (p *Platform) Reply(ctx context.Context, rctx any, content string) error {
return p.post(ctx, rctx, content)
}
func (p *Platform) Send(ctx context.Context, rctx any, content string) error {
return p.post(ctx, rctx, content)
}
// uploadAttachment uploads raw bytes to the Chat media endpoint using a
// multipart/related request and returns the attachmentDataRef resource name.
func (p *Platform) uploadAttachment(ctx context.Context, space, filename, mimeType string, data []byte) (string, error) {View on GitHub (pinned to 4000b2338a)
Solutions
- Treat the send as delivered (status was 2xx) and log the drain error as a warning rather than re-sending, to avoid duplicate messages
- Retry on the next send; transient resets typically resolve on a fresh connection
- If frequent, disable HTTP keep-alive reuse or fix proxy idle-timeout settings between the host and googleapis.com
Example fix
// before
if _, err := io.Copy(io.Discard, resp.Body); err != nil {
return fmt.Errorf("googlechat: drain response body: %w", err) // treated as send failure
}
// after
if _, err := io.Copy(io.Discard, resp.Body); err != nil {
slog.Warn("googlechat: response drain failed; message likely delivered", "err", err)
_ = resp.Body.Close()
return nil
} Defensive patterns
Strategy: try-catch
Try / catch
if err := p.post(ctx, rc, content); err != nil {
if strings.Contains(err.Error(), "drain response body") {
slog.Warn("googlechat: response drain failed after 2xx; treating send as delivered", "err", err)
return nil
}
return err
} Prevention
- Never auto-retry sends that reached a 2xx status — dedupe on message side instead
- Configure proxy/load-balancer idle timeouts above the client's keep-alive interval
- Monitor drain errors as a network-health signal; escalate if frequent
When it happens
Trigger: Reading the 2xx response body fails due to connection reset, TLS truncation, proxy timeouts, or keep-alive connections closed by the server/proxy before the body finished arriving.
Common situations: Flaky networks or aggressive proxies/LBs closing idle keep-alive connections; mobile/VPN link drops; Google-side connection resets under load.
Related errors
- googlechat: close response body: %w
- googlechat: drain attachment create response body: %w
- googlechat: send preview: %w
- range chunk retries exhausted
- request usage endpoint: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/1b58ef31d5bd46ba.
Report an issue: GitHub.