siyuan-note/siyuan · error
read body failed: %s
Error message
read body failed: %s
What it means
Returned at webfetch.go:75 when io.ReadAll(io.LimitReader(resp.Body, maxReadBytes)) fails. Headers were received fine, but the body stream broke partway through. The %s is the io error (e.g. connection reset, read deadline, unexpected EOF).
Source
Thrown at kernel/util/webfetch.go:75
}
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 251596fc0d)
Solutions
- Retry the fetch once — body-stream errors are frequently transient.
- If repeatable, test with `curl --limit-rate` and a longer timeout to characterise the drop.
- Check whether a proxy/VPN in the path is killing long responses.
- For very slow links, raise the httpclient read timeout if configurable in your build.
Defensive patterns
Strategy: retry
Type guard
func isReadBodyFailed(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "read body failed:")
} Try / catch
out, err := util.WebFetch(raw, "markdown")
if err != nil && isReadBodyFailed(err) {
// mid-stream drop: retry once
out, err = util.WebFetch(raw, "markdown")
} Prevention
- Body-stream breaks are usually transient — retry once.
- On flaky links, characterise the drop with curl and a longer timeout before blaming content.
- Keep read timeouts generous enough for slow CDNs.
When it happens
Trigger: Connection reset by peer mid-download, read timeout (client or server side), server closing the keep-alive socket early, TLS renegotiation failure, or the process hitting its read deadline on a slow link.
Common situations: Unstable mobile/tethered network, slow CDN that times out, server killing slow clients, intermediary (proxy/NAT) dropping idle connections.
Related errors
- web search read response failed: %s
- read custom emoji response failed: %w
- read body failed: %s
- read body failed: %s
- fetch failed: %s
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/a91247c94c0f4b25.
Report an issue: GitHub.