chenhg5/cc-connect · error
weixin: %s: read body: %w
Error message
weixin: %s: read body: %w
What it means
post() fails while reading the response body with io.ReadAll (bounded by maxIlinkHTTPResponseBody = 64 MiB via io.LimitReader). This wraps I/O errors from the connection while draining the body, e.g. the server or an intermediary closed the connection mid-response.
Source
Thrown at platform/weixin/client.go:109
}
if c.routeTag != "" {
req.Header.Set("SKRouteTag", c.routeTag)
}
client := c.httpClient
if timeout > 0 {
// Dedicated client so long-poll does not inherit short Timeout from default client.
client = c.longPollClient(timeout)
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("weixin: %s: %w", label, err)
}
defer resp.Body.Close()
raw, err := io.ReadAll(io.LimitReader(resp.Body, maxIlinkHTTPResponseBody+1))
if err != nil {
return nil, fmt.Errorf("weixin: %s: read body: %w", label, err)
}
if len(raw) > maxIlinkHTTPResponseBody {
return nil, fmt.Errorf("weixin: %s: response body exceeds %d bytes", label, maxIlinkHTTPResponseBody)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("weixin: %s: http %d: %s", label, resp.StatusCode, truncateForLog(raw, 512))
}
return raw, nil
}
func truncateForLog(b []byte, max int) string {
s := string(b)
if len(s) <= max {
return s
}
return s[:max] + "…"
}
View on GitHub (pinned to 4000b2338a)
Solutions
- Retry the request — the error is usually transient connection breakage
- Check for intermediary proxies/LBs with aggressive idle timeouts and raise them
- Inspect the wrapped %w error (e.g. 'unexpected EOF', 'connection reset') to identify the transport cause
- Ensure stable network for the host running cc-connect; log the label to know which API call failed
Example fix
// before: one-shot post
raw, err := c.post(ctx, "ilink/bot/getupdates", payload, timeout, "getUpdates")
// after: single retry on body-read failure
raw, err := c.post(ctx, "ilink/bot/getupdates", payload, timeout, "getUpdates")
if err != nil && strings.Contains(err.Error(), "read body") {
raw, err = c.post(ctx, "ilink/bot/getupdates", payload, timeout, "getUpdates")
} Defensive patterns
Strategy: retry
Try / catch
raw, err := c.post(ctx, ep, payload, timeout, label)
if err != nil && strings.Contains(err.Error(), "read body") {
time.Sleep(500 * time.Millisecond)
raw, err = c.post(ctx, ep, payload, timeout, label) // one retry
} Prevention
- Keep connections on stable networks; avoid flaky uplinks for the bot host
- Raise idle/read timeouts on any intermediary proxy or load balancer
- Keep getUpdates batches small by polling regularly
- Check the wrapped cause ('unexpected EOF', 'reset by peer') to target the right network fix
When it happens
Trigger: io.ReadAll returns an error during body read — abrupt TCP reset, connection closed early by the server/proxy, or read deadline expiry mid-body.
Common situations: Server crashes or load balancer resets mid-response; proxy killing long responses; flaky mobile/hotspot networking on the host running cc-connect.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/e53ebf558f4d51bd.
Report an issue: GitHub.