siyuan-note/siyuan · error
notebook [ ] not found for document [ ]
Error message
notebook [%s] not found for document [%s]
What it means
Thrown during document-tree sorting (DocSort / ReorderDocTree path) after resolving each requested item to a block tree entry. The block exists and is a valid root document, but its notebook (box) cannot be found in the currently opened notebook set, so the sort plan cannot be built. The kernel refuses to sort documents whose parent notebook is closed, removed, or otherwise absent from Conf.Box.
Solutions
- Re-open the notebook containing the document (Conf.Box / notebook list API) and retry the sort
- Re-fetch the current document list so the IDs passed to the sort API are fresh
- Verify the notebook still exists in the workspace data directory and was not renamed/deleted
- Filter the sort request to drop documents whose notebooks are not currently opened
Example fix
// before
api.post('/api/filetree/docSort', {ids: staleIDs})
// after
const opened = (await api.post('/api/notebook/lsNotebooks')).data.notebooks
const valid = staleIDs.filter(id => opened.some(nb => nb.id === boxOf(id)))
api.post('/api/filetree/docSort', {ids: valid}) Defensive patterns
Strategy: validation
Validate before calling
// Go-style caller check before sorting
const nb = (await api.post('/api/notebook/lsNotebooks')).data.notebooks.find(n => n.id === boxID)
if (!nb) throw new Error(`notebook ${boxID} is not opened`) Try / catch
try { await sortDocs(ids) } catch (e) { if (String(e.msg).includes('not found for document')) { await refreshNotebookList(); retry(); } else { throw e } } Prevention
- Re-fetch the notebook list before any batch document operation
- Treat document IDs as ephemeral; never persist them across sessions
- Listen for notebook close/delete push events and invalidate cached ID sets
When it happens
Trigger: Calling the doc sorting API (e.g. /api/filetree/docSort or ReorderDocTree) with a document ID whose bt.BoxID is not among the currently opened notebooks (nil == boxes[bt.BoxID]). Happens when the notebook was closed, renamed, or removed between client-side listing and the sort call.
Common situations: Stale client state: UI still holds document IDs from a notebook that was closed or deleted in another window; syncing removed a notebook; a script passes IDs collected earlier against a fresh kernel instance with fewer notebooks open.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- sort target document
- Conf.Language(0)
- document [ ] could not be read
- source document [ ] could not be read
- source document [ ] is unavailable
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/41a5589cf41e9854.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/file.go:2942
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
}
group = &docSortGroup{
fullSortIDs: fullSortIDs,
changed: map[string]int{},
parentSorts: map[string]map[string]int{},
}View on GitHub (pinned to 9f775e8a12)