siyuan-note/siyuan · error
read body failed:
Error message
read body failed:
What it means
HTTPRequest reads the response body with io.ReadAll(io.LimitReader(resp.Body, maxReadBytes)). If that read fails — typically a network interruption mid-body, a TLS/connection reset, or the read hitting the 30-second client timeout — the error is wrapped as "read body failed: <cause>". This happens after a successful response header, so statusCode and contentType may already be set.
Source
Thrown at kernel/util/httprequest.go:356
return 0, "", "", errors.New("nil response")
}
defer resp.Body.Close()
statusCode = resp.StatusCode
contentType = resp.Header.Get("Content-Type")
maxReadBytes := int64(maxHTTPRequestBytes)
if !isTextContentType(contentType) {
maxReadBytes = maxHTTPRequestFileBytes
}
// ContentLength 为 -1(chunked)时跳过大小预检,交由 LimitReader 兜底截断。
if resp.ContentLength > maxReadBytes {
return statusCode, contentType, "", errors.New("response too large")
}
respBody, rerr := io.ReadAll(io.LimitReader(resp.Body, maxReadBytes))
if rerr != nil {
return statusCode, contentType, "", errors.New("read body failed: " + rerr.Error())
}
// 二进制响应落盘,返回文件路径,供智能体按需进一步处理。
if !isTextContentType(contentType) {
importDir := filepath.Join(TempDir, "import")
if merr := os.MkdirAll(importDir, 0755); merr != nil {
return statusCode, contentType, "", errors.New("create import dir failed: " + merr.Error())
}
filename := extractFilename(rawURL, contentType)
filePath := filepath.Join(importDir, filename)
if werr := os.WriteFile(filePath, respBody, 0644); werr != nil {
return statusCode, contentType, "", errors.New("write file failed: " + werr.Error())
}
return statusCode, contentType, fmt.Sprintf("Saved to: %s (%d bytes)", filePath, len(respBody)), nil
}
return statusCode, contentType, truncateRunes(string(respBody), maxHTTPRequestChars), nil
}View on GitHub (pinned to 8641553a1f)
Solutions
- Retry the request — transient network failures are the most common cause
- Check the wrapped cause after "read body failed: " (context deadline exceeded, connection reset, unexpected EOF) and address it specifically
- Reduce response size (pagination) so the body transfer completes within the 30-second client timeout
- Verify proxy stability if HTTP_PROXY/SOCKS5 proxies are configured, since tunnel drops surface here
- If it consistently fails for one host, test the URL with curl to determine whether the server itself aborts transfers
Example fix
// before: single attempt
status, ct, text, err := util.HTTPRequest("GET", url, nil, "")
// after: retry transient failures
var status int; var ct, text string; var err error
for i := 0; i < 3; i++ {
status, ct, text, err = util.HTTPRequest("GET", url, nil, "")
if err == nil || !strings.Contains(err.Error(), "read body failed") { break }
time.Sleep(time.Second)
} Defensive patterns
Strategy: retry
Try / catch
var status int; var ct, text string; var err error
for attempt := 0; attempt < 3; attempt++ {
status, ct, text, err = util.HTTPRequest("GET", url, nil, "")
if err == nil || !strings.Contains(err.Error(), "read body failed") {
break
}
time.Sleep(time.Duration(attempt+1) * time.Second)
} Prevention
- Retry transient body-read failures with exponential backoff
- Keep responses small (pagination) so transfers complete well within the 30-second client timeout
- Check proxy stability if HTTP_PROXY/HTTPS_PROXY/SOCKS5 is configured — tunnel drops surface as body read errors
- Parse the wrapped cause (context deadline exceeded, connection reset, unexpected EOF) to choose between retry and config changes
When it happens
Trigger: HTTPRequest() where the connection drops or times out while streaming the response body, or the server closes the connection prematurely (chunked encoding aborted), or a proxy tunnel is severed mid-transfer.
Common situations: Flaky Wi-Fi/mobile networks, proxies killing long transfers, servers with keep-alive races, or responses taking longer than the 30-second ssrfSafeClient timeout on slow links.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- download failed:
- read body failed: %s
- nil response
- download failed (tried main and master): %v
- read body failed: %s
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/b589bd89da2342f0.
Report an issue: GitHub.