siyuan-note/siyuan · error

document [%s] not found in opened and unlocked notebooks

Error message

document [%s] not found in opened and unlocked notebooks

What it means

Thrown by SetFileTreeSort when a document sort item fails one of two conditions: treenode.GetBlockTree(item.ID) returns nil (the block does not exist in the block tree), or the block's notebook (bt.BoxID) is not present in the openedBoxes map (built from Conf.GetOpenedBoxes()). Only documents in notebooks that are currently open and unlocked can have their sort order persisted.

Source

Thrown at kernel/model/file.go:2612

			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)
		}
		if bt.ID != bt.RootID || "d" != bt.Type || IsBoxDoc(bt.BoxID, bt.RootID) {
			return ret, fmt.Errorf("block [%s] is not a sortable document", item.ID)
		}
		if nil == boxes[bt.BoxID] {
			return ret, fmt.Errorf("notebook [%s] not found for document [%s]", bt.BoxID, item.ID)
		}
		docPlans = append(docPlans, &docSortPlan{item: item, boxID: bt.BoxID, parentPath: path.Dir(bt.Path)})
	}

	docGroups := map[string]*docSortGroup{}
	for _, plan := range docPlans {
		group := docGroups[plan.boxID]
		if nil == group {
			confPath := filepath.Join(util.DataDir, plan.boxID, ".siyuan", "sort.json")
			fullSortIDs, readErr := readSortConfMap(confPath)
			if readErr != nil {
				return ret, readErr

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Ensure the notebook containing the document is open and unlocked — check via GET /api/notebook/lsNotebooks and open it if closed.
  2. If the document was deleted, refresh the file tree so the UI no longer references the stale block ID.
  3. If building an API client, verify each docSorts ID exists via treenode.GetBlockTree or a block lookup endpoint before submitting the sort payload.

Example fix

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

// after
const { boxes } = await get('/api/notebook/lsNotebooks')
const openBoxIds = new Set(boxes.filter(b => !b.closed).map(b => b.id))
// only submit docs whose notebook is currently open
const safeDocSorts = docSorts.filter(item => openBoxIds.has(docNotebookMap[item.id]))
await post('/api/filetree/setFileTreeSort', { notebookSorts: [], docSorts: safeDocSorts })
Defensive patterns

Strategy: validation

Validate before calling

// Only submit doc sort items for documents in open, unlocked notebooks
const { boxes } = await get('/api/notebook/lsNotebooks')
const openBoxIds = new Set(boxes.filter(b => !b.closed).map(b => b.id))
// For each docSorts item, verify its notebook is open before submitting
const safeDocSorts = docSorts.filter(item => {
  const bt = blockTreeCache[item.id]
  return bt && openBoxIds.has(bt.boxID)
})

Prevention

When it happens

Trigger: Calling POST /api/filetree/setFileTreeSort with a docSorts entry whose ID does not exist in the block tree (deleted or invalid block), or whose containing notebook is closed or locked. The check `nil == openedBoxes[bt.BoxID]` catches closed notebooks and locked/encrypted notebooks since GetOpenedBoxes only returns open, unlocked boxes.

Common situations: Document was deleted in another session but the current tab's file tree still shows it; the notebook containing the document was closed (not just collapsed — fully closed) after the tree was loaded; an encrypted notebook was locked after the tree UI was rendered; an external API client using a stale or fabricated block ID.

Related errors


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