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

fileTreeRequestFields decodes the request body of a filetree API endpoint with json.Decoder.Decode. When decoding returns io.EOF it means the HTTP body was absent or cut off before any complete JSON value was read, so the library raises this explicit message instead of a bare EOF. It wraps the result into 'Parses request [%s] failed: ...' for the endpoint path.

Solutions

  1. Send a valid JSON object as the request body, e.g. {"id":"..."} instead of an empty body
  2. Verify the HTTP client actually serializes the payload (check fetchPost second argument is an object, not undefined)
  3. Log the raw body length before sending and compare with Content-Length to find truncation
  4. Check proxies/gateways for body size limits or buffering issues

Example fix

// before
fetchPost("/api/filetree/removeDoc", undefined);
// after
fetchPost("/api/filetree/removeDoc", { id: "20240101120000-abcdefg" });
Defensive patterns

Strategy: validation

Validate before calling

const body = JSON.stringify(payload ?? {});
if (body.length <= 2) throw new Error("request payload must be a non-empty JSON object");

Type guard

const hasBody = (p) => p !== null && p !== undefined && typeof p === "object" && Object.keys(p).length > 0;

Try / catch

try {
  const res = await fetchPost(path, payload);
} catch (e) {
  if (String(e.message).includes("empty or truncated (EOF)")) {
    // resend with a valid JSON object body
  }
}

Prevention

When it happens

Trigger: POSTing to any /api/filetree/* contract endpoint with an empty body, a Content-Length shorter than the actual body, or a connection closed mid-body (truncated transfer).

Common situations: fetchPost called with undefined/omitted payload; proxies or gateways truncating bodies; a client forgetting to set the request body on a POST; network interruptions during large uploads.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/8c4d6baa56d24efa. Report an issue: GitHub.

Appendix: source

Thrown at kernel/apicontract/filetree_input.go:23

	"encoding/json"
	"errors"
	"fmt"
	"io"
	"reflect"
	"strings"
)

type fileTreeFields map[string]json.RawMessage

func fileTreeRequestFields(reader io.Reader, path string) (fields fileTreeFields, err error) {
	var raw json.RawMessage
	err = json.NewDecoder(reader).Decode(&raw)
	if err == nil {
		fields, err = legacyJSONValue[fileTreeFields](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(), "apicontract.fileTreeFields", "map[string]interface {}")
		err = fmt.Errorf("Parses request [%s] failed: %s", path, detail)
	}
	return
}

func fileTreeJSONDecoder[Request, Data any](endpoint *Endpoint[Request, Data]) {
	endpoint.decodeRequest = func(reader io.Reader) (request Request, err error) {
		fields, err := fileTreeRequestFields(reader, endpoint.definition.Path)
		if err == nil {
			request, err = fileTreeBind[Request](fields)
		}
		return request, err
	}
}

func (r FileTreePathRequest) PathError() error { return r.pathError }

View on GitHub (pinned to 9f775e8a12)