siyuan-note/siyuan · error
failed to read body
Error message
failed to read body: %s
What it means
The AISaveSession endpoint reads the entire raw request body with io.ReadAll; if that read fails the error is wrapped as 'failed to read body: <err>'. This indicates the request body could not be read at the transport/IO level before any JSON parsing happened.
Solutions
- Retry the request with an intact body over a stable connection
- Check intermediary proxies/logs for aborted transfers or body size limits
- Ensure the client sends a valid, complete request body with correct Content-Length/chunked framing
- Increase proxy/client body size limits if the session payload is large
Defensive patterns
Strategy: retry
Validate before calling
if (!(body instanceof Uint8Array) || body.length === 0) throw new Error("empty request body"); Try / catch
try { await post("/api/ai/session/save", body); } catch (e) { if (e instanceof TypeError || /network|body/i.test(String(e))) { /* retry with backoff */ } else throw e; } Prevention
- Avoid proxies/body-size limits truncating large session payloads
- Use a standard HTTP client that sets correct Content-Length or chunked encoding
- Log and surface aborted-connection errors client-side
When it happens
Trigger: POST to the AI session save endpoint where the request body stream errors: aborted connections, request smuggling/mis-framed chunked bodies, proxies terminating mid-body, or passing a failing reader in in-process tests.
Common situations: Reverse proxies (nginx/CDN) dropping large uploads, client disconnecting before the body finishes, network interruptions on mobile, broken custom HTTP clients sending malformed chunked encoding.
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
- authentication probe returned HTTP " + response.status
- boot progress request returned HTTP " + response.status
- discover OIDC provider failed
- download custom emoji failed
- download custom emoji failed with status
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/b12feb1139b5a12b.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/ai_input.go:70
if raw := fields["providerConfig"]; len(raw) > 0 && !bytes.Equal(raw, []byte("null")) {
value, err := legacyJSONValue[SettingProvider](raw)
if err != nil {
err = fmt.Errorf("%s", strings.NewReplacer("SettingProvider.", "Provider.", "SettingModel.", "Model.", "apicontract.SettingProvider", "conf.Provider", "apicontract.SettingModel", "conf.Model").Replace(err.Error()))
}
request.ProviderConfig = &value
request.providerError = err
}
return request
}
func init() {
aiStructDecoder(&AIEditorChat, "aiEditorChatReq")
aiStructDecoder(&AIAgentChat, "agentChatReq")
aiStructDecoder(&AIGetSession, "agentSessionGetReq")
AISaveSession.decodeRequest = func(reader io.Reader) (value AISession, err error) {
value.raw, err = io.ReadAll(reader)
if err != nil {
err = fmt.Errorf("failed to read body: %s", err)
}
return
}
aiStructDecoder(&AIAgentConfirm, "agentConfirmReq")
aiStructDecoder(&AIAgentSetPermission, "agentPermissionReq")
aiStructDecoder(&AIAgentQuestion, "agentQuestionReq")
aiStructDecoder(&AIAgentBrowserCapabilityResult, "agentBrowserCapabilityResultReq")
aiStructDecoder(&AIAgentTitle, "agentTitleReq")
aiStructDecoder(&AIListSessions, "agentSessionsReq")
aiStructDecoder(&AIRemoveSession, "agentSessionDeleteReq")
aiStructDecoder(&AIGetSkill, "skillGetReq")
aiStructDecoder(&AISaveSkill, "skillSaveReq")
aiStructDecoder(&AIRemoveSkill, "skillRemoveReq")
aiStructDecoder(&AIRenameSkill, "skillRenameReq")
aiJSONDecoder(&AIChatGPT, func(fields fileTreeFields) (value AIMessageRequest, err error) {
value.Msg, err = aiLegacyString(fields, "msg", true, true)
return
})View on GitHub (pinned to 9f775e8a12)