siyuan-note/siyuan · error
the request body is empty or truncated (EOF)
Error message
the request body is empty or truncated (EOF)
What it means
syncRequestFields parses the whole body of sync-related endpoints (/api/sync/setSyncEnable, setSyncMode, setSyncProvider, setCloudSyncDir, performSync, etc.). If the JSON decoder hits io.EOF — meaning the request body is completely empty or was cut off mid-stream — it is replaced with this explicit message before being wrapped in 'Parses request [...] failed'.
Solutions
- Send a valid JSON object body, e.g. {"enabled":true} for /api/sync/setSyncEnable
- Add Content-Type: application/json and verify Content-Length matches the body
- Check client code that the body variable is actually passed and not undefined/null
Example fix
// before
curl -X POST http://127.0.0.1:6806/api/sync/setSyncEnable -H 'Authorization: Token xxx'
// after
curl -X POST http://127.0.0.1:6806/api/sync/setSyncEnable -H 'Authorization: Token xxx' -H 'Content-Type: application/json' -d '{"enabled":true}' Defensive patterns
Strategy: validation
Validate before calling
if (!body || typeof body !== 'object') throw new Error('sync request body required'); Type guard
null
Try / catch
try { const res = await fetchPost(path, payload); } catch (e) { if (e.msg && e.msg.includes('empty or truncated')) fixRequestBody(); } Prevention
- Always pass a JSON body object to sync endpoints
- Set Content-Type: application/json
- Check Content-Length when behind a proxy
When it happens
Trigger: POSTing to any of the /api/sync/* contract endpoints with no body, a Content-Length of 0, or a truncated/chunked stream; sending a body that is only whitespace; a proxy dropping the body.
Common situations: curl -X POST without -d; a fetch() call forgetting the body argument; network interruption between client and kernel truncating the body; misconfigured reverse proxy buffering.
Related errors
- Parses request [ ] failed
- the request body is empty or truncated (EOF)
- the request body is empty or truncated (EOF)
- map[string]json.RawMessage
- Parses request [ ] failed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/763f0b47eeb1a9fd.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/sync.go:151
func syncConfigError(err error, name string) error {
if err == nil {
return nil
}
detail := strings.ReplaceAll(err.Error(), "apicontract.Sync"+name, "conf."+name)
return errors.New(strings.ReplaceAll(detail, "struct field Sync"+name+".", "struct field "+name+"."))
}
// syncRequestFields 保留整份请求的 JSON 数字解析、重复字段和首个对象读取语义。
func syncRequestFields(reader io.Reader, path string) (fields map[string]json.RawMessage, err error) {
var raw json.RawMessage
err = json.NewDecoder(reader).Decode(&raw)
if err == nil {
fields, err = legacyJSONValue[map[string]json.RawMessage](raw)
}
if err != nil {
if errors.Is(err, io.EOF) {
err = errors.New("the request body is empty or truncated (EOF)")
}
detail := strings.ReplaceAll(err.Error(), "map[string]json.RawMessage", "map[string]interface {}")
err = fmt.Errorf("Parses request [%s] failed: %s", path, detail)
}
return
}
func init() {
for _, endpoint := range []*Endpoint[SyncEnabledRequest, Null]{&SetSyncEnable, &SetSyncPerception, &SetSyncGenerateConflictDoc} {
path := endpoint.definition.Path
endpoint.decodeRequest = func(reader io.Reader) (r SyncEnabledRequest, err error) {
fields, err := syncRequestFields(reader, path)
if err == nil {
r.Enabled, err = legacyField[bool](fields, "enabled", "Boolean", true)
}
return r, err
}
}View on GitHub (pinned to 9f775e8a12)