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, ¬ebookSortPlan{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, readErrView on GitHub (pinned to 251596fc0d)
Solutions
- Ensure the notebook containing the document is open and unlocked — check via GET /api/notebook/lsNotebooks and open it if closed.
- If the document was deleted, refresh the file tree so the UI no longer references the stale block ID.
- 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
- Check that the document's notebook is open and unlocked before including it in a sort payload.
- Listen for notebook close/lock WebSocket events and update UI state to prevent stale sort submissions.
- Handle document deletion events to remove stale block IDs from the file tree.
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
- notebook [%s] not found
- duplicate notebook ID [%s]
- duplicate document ID [%s]
- block [%s] is not a sortable document
- notebook [%s] not found for document [%s]
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/f6adcad15020e923.
Report an issue: GitHub.