siyuan-note/siyuan · error

notebook [%s] not found

Error message

notebook [%s] not found

What it means

Thrown by SetFileTreeSort when a SortItem in notebookSorts references a notebook ID that does not exist in the current configuration (the boxes map, built from Conf.GetBoxes()). This means the client is trying to persist a sort order for a notebook that has been deleted, was never created, or whose ID was fabricated.

Source

Thrown at kernel/model/file.go:2594

	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")
		}
		if _, ok := docIDs[item.ID]; ok {
			return ret, fmt.Errorf("duplicate document ID [%s]", item.ID)
		}
		docIDs[item.ID] = struct{}{}

		bt := treenode.GetBlockTree(item.ID)
		if nil == bt || nil == openedBoxes[bt.BoxID] {
			return ret, fmt.Errorf("document [%s] not found in opened and unlocked notebooks", item.ID)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Refresh the notebook list from the kernel (e.g. GET /api/notebook/lsNotebooks) before attempting to persist sort order, so the UI only sends IDs that currently exist.
  2. If building an API client, validate each notebookSorts ID against the list of known box IDs returned by the notebook listing endpoint before calling setFileTreeSort.
  3. If the error persists, check whether the notebook was deleted by another session or via sync — reload the workspace configuration.

Example fix

// before
await post('/api/filetree/setFileTreeSort', { notebookSorts, docSorts: [] })

// after
const { notebooks } = await get('/api/notebook/lsNotebooks')
const validIds = new Set(notebooks.map(n => n.id))
const filtered = notebookSorts.filter(item => validIds.has(item.id))
await post('/api/filetree/setFileTreeSort', { notebookSorts: filtered, docSorts: [] })
Defensive patterns

Strategy: validation

Validate before calling

// Validate notebook IDs exist before persisting sort order
const { notebooks } = await get('/api/notebook/lsNotebooks')
const validBoxIds = new Set(notebooks.map(n => n.id))
const validNotebookSorts = notebookSorts.filter(item => validBoxIds.has(item.id))

Prevention

When it happens

Trigger: Calling POST /api/filetree/setFileTreeSort with a notebookSorts entry whose id does not match any notebook returned by Conf.GetBoxes(). Common when a notebook was deleted in another session/tab but the file tree UI in the current session still holds the stale ID and includes it in a sort payload.

Common situations: Stale UI state after a notebook was removed via a different device or sync; an external API client using a hardcoded or cached notebook ID that no longer exists; race condition where a notebook is deleted between the UI loading the tree and the user reordering it.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/9b0b0ed4e96471e8. Report an issue: GitHub.