{"record":{"id":"2ab219536f4ac740","repo":"siyuan-note/siyuan","slug":"the-request-body-is-empty-or-truncated-eof","errorCode":null,"errorMessage":"the request body is empty or truncated (EOF)","messagePattern":"the request body is empty or truncated \\(EOF\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/block_remaining.go","lineNumber":59,"sourceCode":"}\n\n// 特殊解码仅保留这些入口的条件参数和结构体绑定语义，响应仍受各自的契约约束。\nfunc init() {\n\tCheckBlockRef.decodeRequest = decodeCheckBlockRef\n\tGetHeadingLevelTransaction.decodeRequest = decodeHeadingLevel\n\tGetDocHeadingLevelTransaction.decodeRequest = func(reader io.Reader) (request DocHeadingLevelRequest, err error) {\n\t\tif json.NewDecoder(reader).Decode(&request) != nil {\n\t\t\terr = errors.New(\"invalid heading conversion parameters\")\n\t\t}\n\t\treturn\n\t}\n}\n\nfunc blockRequestFields(reader io.Reader, path string) (fields map[string]json.RawMessage, err error) {\n\terr = json.NewDecoder(reader).Decode(&fields)\n\tif err != nil {\n\t\tif errors.Is(err, io.EOF) {\n\t\t\terr = errors.New(\"the request body is empty or truncated (EOF)\")\n\t\t}\n\t\terr = fmt.Errorf(\"Parses request [%s] failed: %s\", path, err)\n\t}\n\treturn\n}\n\nfunc decodeCheckBlockRef(reader io.Reader) (request CheckBlockRefRequest, err error) {\n\tfields, err := blockRequestFields(reader, \"/api/block/checkBlockRef\")\n\tif err != nil {\n\t\treturn request, err\n\t}\n\tif raw, present := fields[\"scope\"]; present {\n\t\tif bytes.Equal(raw, []byte(\"null\")) || json.Unmarshal(raw, &request.Scope) != nil {\n\t\t\treturn request, errors.New(\"Field [scope] should be of type [String]\")\n\t\t}\n\t}\n\tif strings.TrimSpace(request.Scope) == \"\" {\n\t\trequest.Scope = \"blocks\"","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/block_remaining.go#L41-L77","documentation":"The shared request-field decoder reads the body into a JSON object map. When json.Decode returns io.EOF the body was empty or cut short before any JSON value; the decoder substitutes this explicit message instead of the generic parse-failure text so callers can distinguish missing bodies from malformed ones.","triggerScenarios":"POSTing to any endpoint that goes through blockRequestFields (checkBlockRef, heading-level transactions, bazaar requests, AV-bound decoders) with a zero-length body, or a body stream that closes before emitting any bytes.","commonSituations":"HTTP clients forgetting to attach the JSON body, an upstream proxy/load balancer or gzip layer truncating the request, or read timeouts on slow uploads cutting the stream early.","solutions":["Ensure the HTTP client actually serializes and attaches a JSON body to the POST.","Log the raw request body length server-side or client-side to confirm it is non-empty.","Check intermediate proxies/gateways for body-size limits or truncation.","Handle the error explicitly on the client: retry once with a re-serialized payload if the body may have been dropped."],"exampleFix":"// before\nfetch(\"/api/block/checkBlockRef\", {method: \"POST\"}) // no body\n// after\nfetch(\"/api/block/checkBlockRef\", {method: \"POST\", body: JSON.stringify({ids: [\"20240101120000-abcdefg\"]})})","handlingStrategy":"validation","validationCode":"if (!bodyString || bodyString.length === 0) { throw new Error(\"refusing to send empty request body\"); }","typeGuard":null,"tryCatchPattern":"try {\n  await post(path, body);\n} catch (e) {\n  if (String(e.message).includes(\"empty or truncated\")) {\n    console.error(\"Body was empty/truncated; resending...\");\n    await post(path, JSON.stringify(body)); // re-serialize and retry once\n  } else { throw e; }\n}","preventionTips":["Always pass a serialized body to POST requests","Check HTTP client options that can drop bodies (redirects on POST, GET downgrades)","Verify no proxy/gateway strips or truncates bodies","Log request body length before sending in debug mode"],"tags":["http","empty-body","json","api"],"backgroundTag":"empty-response-body","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}