Tencent/WeKnora · error
read body failed: %w
Error message
read body failed: %w
What it means
Returned when reading the HTTP response body fails after a 2xx status. The body is read through io.LimitReader capped at maxSize (10 MB for feeds, 5 MB for articles), so this error comes from a broken/truncated connection, an unexpected EOF, a decompression failure (e.g. malformed gzip), or the request context timing out mid-read.
Source
Thrown at internal/datasource/connector/rss/client.go:89
}
if req.Header.Get("Accept") == "" {
req.Header.Set("Accept",
"application/rss+xml, application/atom+xml, application/xml, text/xml, application/json, text/html;q=0.9, */*;q=0.8")
}
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("fetch failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("HTTP %d %s", resp.StatusCode, resp.Status)
}
body, err := io.ReadAll(io.LimitReader(resp.Body, maxSize))
if err != nil {
return nil, fmt.Errorf("read body failed: %w", err)
}
return body, nil
}
// fetchFeed retrieves the raw bytes of a feed document.
func (c *client) fetchFeed(ctx context.Context, feedURL string) ([]byte, error) {
return c.fetch(ctx, feedURL, maxFeedSize, true)
}
// extractArticle fetches an article page and returns the readability-cleaned
// main content as HTML, plus the extracted title (may be empty). Returns an
// error if the page can't be fetched or no readable content is found, so the
// caller can fall back to feed-provided content.
func (c *client) extractArticle(ctx context.Context, articleURL string) (contentHTML, title string, err error) {
body, err := c.fetch(ctx, articleURL, maxArticleSize, false)
if err != nil {
return "", "", err
}View on GitHub (pinned to 988cbb0330)
Solutions
- Retry the fetch — truncation is usually transient; wrap the call in a retry with backoff.
- If timeouts recur, reduce the amount fetched (trim the feed) or increase requestTimeout; note the maxSize LimitReader caps memory but not time.
- Bypass or fix a misconfigured proxy/CDN that is corrupting Content-Encoding; test with curl --compressed.
- Check server-side logs on the feed host for crashes or connection resets.
Example fix
// before
data, err := cli.fetchFeed(ctx, feedURL)
// after
var data []byte
var err error
for i := 0; i < 3; i++ {
data, err = cli.fetchFeed(ctx, feedURL)
if err == nil || !isTransientReadError(err) {
break
}
time.Sleep(time.Duration(1<<i) * time.Second)
} Defensive patterns
Strategy: retry
Try / catch
data, err := cli.fetchFeed(ctx, feedURL)
if err != nil {
if isTruncated(err) { // io.ErrUnexpectedEOF / context deadline in message
ctx2, cancel := context.WithTimeout(ctx, 60*time.Second)
defer cancel()
data, err = cli.fetchFeed(ctx2, feedURL)
}
if err != nil {
return fmt.Errorf("feed %s: %w", feedURL, err)
}
} Prevention
- Retry truncated reads — they are almost always transient.
- Raise requestTimeout for known-large or slow feeds.
- Check proxy/CDN Content-Encoding configuration if errors repeat for one host.
- Cap feed sizes server-side so slow streaming is bounded.
When it happens
Trigger: The server closes the connection before sending the full body; a proxy or CDN truncates the response; the response uses gzip/deflate/brotli with corrupt bytes; the 20s context deadline expires while streaming a large body.
Common situations: Flaky mobile/behind-NAT feed hosts dropping connections; misconfigured CDNs sending a Content-Encoding the client cannot decompress; very large feeds on slow links hitting the 20-second timeout; load balancers with short idle timeouts.
Related errors
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/33035a5df03c4c0d.
Report an issue: GitHub.