Tencent/WeKnora · error
read response body: %w
Error message
read response body: %w
What it means
After a successful HTTP response, doRequest reads the whole body with io.ReadAll. If reading fails (connection reset mid-body, premature close, context deadline during read), it wraps the error as "read response body: %w" and, if retries remain, backs off and retries the request.
Source
Thrown at internal/datasource/connector/yuque/client.go:91
logger.Infof(ctx, "[Yuque] %s %s (retry %d/%d)", method, path, attempt, maxRetries)
}
resp, err := c.httpClient.Do(req)
if err != nil {
lastErr = fmt.Errorf("execute request: %w", err)
if attempt < maxRetries {
if sErr := sleepCtx(ctx, backoff[attempt]); sErr != nil {
return sErr
}
continue
}
return lastErr
}
body, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
lastErr = fmt.Errorf("read response body: %w", readErr)
if attempt < maxRetries {
if sErr := sleepCtx(ctx, backoff[attempt]); sErr != nil {
return sErr
}
continue
}
return lastErr
}
bodyPreview := truncate(string(body), 500)
logger.Infof(ctx, "[Yuque] %s %s → status=%d bodyLen=%d body=%s",
method, path, resp.StatusCode, len(body), bodyPreview)
if resp.StatusCode == 429 {
wait := parseRetryAfter(resp.Header.Get("Retry-After"), backoff[min(attempt, len(backoff)-1)])
lastErr = fmt.Errorf("yuque rate limited: status=429 body=%s", bodyPreview)
if attempt < maxRetries {
if sErr := sleepCtx(ctx, wait); sErr != nil {View on GitHub (pinned to 988cbb0330)
Solutions
- Retry — the client already retries automatically; check if retries were exhausted and investigate network stability.
- Increase the context/request timeout so large bodies can be fully read.
- Check intermediary proxies/LBs for connection-reset or idle-timeout issues.
- Verify stable connectivity to www.yuque.com (packet loss, MTU issues).
Example fix
// before ctx, cancel := context.WithTimeout(ctx, 2*time.Second) // after ctx, cancel := context.WithTimeout(ctx, 30*time.Second) // allow full body read
Defensive patterns
Strategy: retry
Type guard
func isBodyReadError(err error) bool {
return strings.Contains(err.Error(), "read response body:")
} Try / catch
err := client.ListBookDocs(ctx, repo, page)
if err != nil && strings.Contains(err.Error(), "read response body:") {
// transient network issue; client already retried — back off and retry at job level
return err
} Prevention
- Use timeouts long enough for the largest expected response.
- Prefer stable networks/regions for long-running sync jobs.
- Investigate proxies/LBs that reset long transfers.
- Log body-length context to distinguish truncation patterns.
When it happens
Trigger: The server or an intermediary (LB/proxy) closes the connection before the full body arrives; network interruption mid-transfer; context deadline exceeded while streaming a large response.
Common situations: Unstable networks or flaky VPNs; very large API responses hitting a short context timeout; load balancers with aggressive idle timeouts; TLS interception proxies resetting connections.
Related errors
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/b60f92bacdc14259.
Report an issue: GitHub.