siyuan-note/siyuan · error

notebook sort item must not be nil

Error message

notebook sort item must not be nil

What it means

SetFileTreeSort builds notebookSortPlan entries from the request's notebookSorts array and rejects a nil element outright. A null entry in the JSON array cannot carry an ID or sort weight, so the entire batch sort fails fast with this error before any file is moved.

Source

Thrown at kernel/model/file.go:2885

	}

	FlushTxQueue()
	fileTreeSortLock.Lock()
	defer fileTreeSortLock.Unlock()
	boxes := map[string]*Box{}
	for _, box := range Conf.GetBoxes() {
		boxes[box.ID] = box
	}
	openedBoxes := map[string]*Box{}
	for _, box := range Conf.GetOpenedBoxes() {
		openedBoxes[box.ID] = box
	}

	notebookPlans := make([]*notebookSortPlan, 0, len(notebookSorts))
	notebookIDs := map[string]struct{}{}
	for _, item := range notebookSorts {
		if nil == item {
			return ret, errors.New("notebook sort item must not be nil")
		}
		if _, ok := notebookIDs[item.ID]; ok {
			return ret, fmt.Errorf("duplicate notebook ID [%s]", item.ID)
		}
		notebookIDs[item.ID] = struct{}{}

		box := boxes[item.ID]
		if nil == box {
			return ret, fmt.Errorf("notebook [%s] not found", item.ID)
		}
		notebookPlans = append(notebookPlans, &notebookSortPlan{item: item, box: box})
	}

	docPlans := make([]*docSortPlan, 0, len(docSorts))
	docIDs := map[string]struct{}{}
	for _, item := range docSorts {
		if nil == item {
			return ret, errors.New("document sort item must not be nil")

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Inspect the request payload and remove null entries from the notebookSorts array before sending.
  2. Fix the client code that constructs the array to filter out undefined/null values (e.g. arr.filter(Boolean)).
  3. If a notebook was deleted, drop it from the sort list instead of sending a placeholder null.

Example fix

// before
fetchPost("/api/filetree/setFileTreeSort", {notebookSorts: [ ...items, removedNotebook ]})
// after
const items = [...items, removedNotebook].filter(Boolean);
fetchPost("/api/filetree/setFileTreeSort", {notebookSorts: items})
Defensive patterns

Strategy: validation

Validate before calling

if (notebookSorts.some(i => i == null)) {
  throw new Error("notebookSorts contains null entries");
}

Type guard

const isValidItem = (i) => i != null && typeof i.id === "string" && i.id.length > 0 && typeof i.sort === "number";

Try / catch

try {
  await api.setFileTreeSort({notebookSorts});
} catch (e) {
  if (String(e).includes("must not be nil")) {
    return api.setFileTreeSort({notebookSorts: notebookSorts.filter(Boolean)});
  }
  throw e;
}

Prevention

When it happens

Trigger: Posting to the file-tree sort API a notebookSorts array containing a JSON null element, e.g. [{"id":"20240101120000-abc","sort":1},null], usually from a client-side array construction bug.

Common situations: Plugin or script building the sort payload by pushing undefined/null items (e.g. array built with holes, JSON.stringify of [undefined]); deserialization of sparse arrays from storage.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/adeb179a185d798d. Report an issue: GitHub.