siyuan-note/siyuan · error

Field [sortMode] is required

Error message

Field [sortMode] is required

What it means

The setDocSortMode contract requires a 'sortMode' field in the request body. The Mode() accessor reads the stored raw JSON for the key and, if the key is absent (or was an empty raw value), returns 'Field [sortMode] is required'. Unlike some optional fields, null is accepted (returning nil), but the key must be present.

Solutions

  1. Add sortMode to the request body as an integer or null
  2. Use a documented sort mode value (e.g. 0 for by name, per API docs)
  3. If the sort should be cleared, send "sortMode": null rather than omitting the field

Example fix

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

Strategy: validation

Validate before calling

if (!Number.isInteger(sortMode) && sortMode !== null) throw new Error("sortMode must be an integer or null");
if (!id?.trim()) throw new Error("id must not be empty");
const body = { id, sortMode }; // key always present

Type guard

const hasSortMode = (b) => "sortMode" in b && (b.sortMode === null || Number.isInteger(b.sortMode));

Prevention

When it happens

Trigger: POST /api/filetree/setDocSortMode with a body that has id but no sortMode key, e.g. {"id":"20240101120000-abcdefg"}.

Common situations: Older clients written before sortMode was required; copy-pasted request bodies missing a field; a UI toggle that serializes only when touched.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at kernel/apicontract/filetree_input.go:123

	// 文档查询复用分组筛选的兼容规则,未知分组和非布尔选项不会生效。
	filter, _ := json.Marshal(map[string]json.RawMessage{"subTypes": fields["querySubTypes"]})
	if fields["querySubTypes"] != nil {
		filtered, err := searchQueryFields(bytes.NewReader(filter), "/api/filetree/getDoc")
		if err != nil {
			return FileTreeGetDocOptions{}, err
		}
		delete(fields, "querySubTypes")
		if value, ok := filtered["subTypes"]; ok {
			fields["querySubTypes"] = value
		}
	}
	return fileTreeBind[FileTreeGetDocOptions](fields)
}

func (r FileTreeSortModeRequest) Mode() (*int, error) {
	raw := r.sortModeFields["sortMode"]
	if len(raw) == 0 {
		return nil, fmt.Errorf("Field [sortMode] is required")
	}
	if bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
		return nil, nil
	}
	var value int
	if err := json.Unmarshal(raw, &value); err != nil {
		return nil, fmt.Errorf("Field [sortMode] must be an integer or null: %s", err)
	}
	return &value, nil
}

func init() {
	fileTreeJSONDecoder(&MoveLocalShorthands)
	fileTreeJSONDecoder(&UpsertIndexes)
	fileTreeJSONDecoder(&RemoveIndexes)
	fileTreeJSONDecoder(&Doc2Heading)
	fileTreeJSONDecoder(&GetHPathByPath)
	fileTreeJSONDecoder(&GetHPathsByPaths)

View on GitHub (pinned to 9f775e8a12)