Tencent/WeKnora · warning

read body: %w

Error message

read body: %w

What it means

DownloadBytes reads the entire response body with io.ReadAll after confirming status 200; an I/O failure mid-read (connection reset, premature close, truncated chunked encoding) is wrapped as "read body: <cause>".

Source

Thrown at internal/utils/httputil.go:35

// raw bytes. It reuses a package-level http.Client with a 60-second timeout.
func DownloadBytes(url string) ([]byte, error) {
	if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
		return nil, fmt.Errorf("unsupported URL scheme: %s", url)
	}
	if err := ValidateURLForSSRF(url); err != nil {
		return nil, fmt.Errorf("URL rejected by SSRF policy: %w", err)
	}
	resp, err := defaultHTTPClient.Get(url)
	if err != nil {
		return nil, fmt.Errorf("HTTP GET: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP %d for %s", resp.StatusCode, url)
	}
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read body: %w", err)
	}
	return data, nil
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Retry the download with exponential backoff — transient resets often succeed on retry
  2. Use a resumable/range-request download for large files
  3. Verify intermediate proxies/CDNs aren't truncating the response
  4. Check server-side stability of the endpoint; for huge payloads consider a different transfer mechanism (fetch in chunks)

Example fix

// before
data, err := DownloadBytes(url) // read body: unexpected EOF
// after
var data []byte
err := retryWithBackoff(3, func() error {
    var e error
    data, e = DownloadBytes(url)
    return e
})
Defensive patterns

Strategy: retry

Try / catch

var data []byte
err := retryWithBackoff(3, time.Second, func() error {
    var e error
    data, e = DownloadBytes(url)
    if e != nil && strings.Contains(e.Error(), "read body:") {
        return e // transient truncation — retry
    }
    return e
})

Prevention

When it happens

Trigger: Calling DownloadBytes when the connection drops while streaming the body: server closes prematurely, network interruption, proxy/CDN truncation, or chunked encoding errors.

Common situations: Flaky mobile/satellite uplinks on the server side, large downloads over unstable connections, aggressive LB idle timeouts killing long transfers, or misbehaving CDNs/proxies cutting responses short.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/322af64bac9ee08f. Report an issue: GitHub.