siyuan-note/siyuan · error
read body failed
Error message
read body failed: %s
What it means
WebFetch reads the response body via io.ReadAll(io.LimitReader(resp.Body, maxReadBytes)); any I/O error during that read (connection reset mid-body, TLS error, timeout while streaming, truncated chunked encoding) is wrapped as 'read body failed: <cause>'. Headers were received fine; the body transfer broke.
Solutions
- Retry the fetch — this is usually transient
- Inspect the wrapped cause after 'read body failed: ' for reset vs timeout specifics
- Prefer smaller, faster endpoints (the shorter the transfer, the lower the interruption risk)
- If persistent, check for middleboxes/proxies between the kernel and the target and raise client timeouts
Example fix
// before
content, err := WebFetch(url, "markdown")
// after
content, err := WebFetch(url, "markdown")
if err != nil && strings.Contains(err.Error(), "read body failed") {
content, err = WebFetch(url, "markdown") // one retry for transient truncation
} Defensive patterns
Strategy: retry
Try / catch
content, err := WebFetch(url, format)
if err != nil && strings.Contains(err.Error(), "read body failed") {
time.Sleep(time.Second)
content, err = WebFetch(url, format) // single retry for transient truncation
} Prevention
- Retry once or twice — mid-body resets are usually transient
- Avoid fetching from known-flaky sources over unstable links
- Prefer smaller endpoints to shorten the transfer window
- Investigate proxies/middleboxes if resets cluster on one network path
When it happens
Trigger: Server closes the connection partway through the body; network interruption during a large transfer; read deadline hit on a slow body; proxy dropping a keep-alive connection mid-response.
Common situations: Flaky mobile/VPN connections; aggressive load balancers killing slow responses; fetching from servers that trickle data and trip timeouts; transient upstream failures behind CDNs.
Related errors
- read body failed:
- web search read response failed
- authentication probe returned HTTP " + response.status
- boot progress request returned HTTP " + response.status
- discover OIDC provider failed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/a91247c94c0f4b25.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/webfetch.go:74
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return "", fmt.Errorf("HTTP %d", resp.StatusCode)
}
contentType := resp.Header.Get("Content-Type")
maxReadBytes := int64(maxWebFetchBytes)
if !strings.HasPrefix(contentType, "text/html") && !strings.HasPrefix(contentType, "text/plain") {
maxReadBytes = maxWebFetchFileBytes
}
if resp.ContentLength > maxReadBytes {
return "", errors.New("response too large")
}
body, err := io.ReadAll(io.LimitReader(resp.Body, maxReadBytes))
if err != nil {
return "", errors.New("read body failed: " + err.Error())
}
if !strings.HasPrefix(contentType, "text/html") && !strings.HasPrefix(contentType, "text/plain") {
importDir := filepath.Join(TempDir, "import")
if merr := os.MkdirAll(importDir, 0755); merr != nil {
return "", errors.New("create import dir failed: " + merr.Error())
}
filename := extractFilename(rawURL, contentType)
filePath := filepath.Join(importDir, filename)
if werr := os.WriteFile(filePath, body, 0644); werr != nil {
return "", errors.New("write file failed: " + werr.Error())
}
return fmt.Sprintf("Saved to: %s (%d bytes)", filePath, len(body)), nil
}
htmlStr := string(body)
isHTML := strings.HasPrefix(contentType, "text/html")View on GitHub (pinned to 9f775e8a12)