siyuan-note/siyuan · error
duplicate notebook ID [%s]
Error message
duplicate notebook ID [%s]
What it means
Thrown by SetFileTreeSort when the notebookSorts slice passed to the API contains two entries with the same ID. The function iterates notebookSorts and builds a deduplication map (notebookIDs); encountering a repeat ID is treated as invalid input and rejected before any sort.json file is written. This protects the on-disk sort configuration from contradictory sort-order assignments for a single notebook.
Source
Thrown at kernel/model/file.go:2588
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, ¬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)View on GitHub (pinned to 251596fc0d)
Solutions
- Deduplicate the notebookSorts array by item.ID on the client side before sending the request, keeping only the entry with the latest sort value.
- If the error originates from a frontend drag-and-drop handler, ensure the source notebook is removed from its old position before inserting it at the new position, so the payload never contains the ID twice.
- Inspect the outgoing POST /api/filetree/setFileTreeSort payload in the browser network tab to find which ID is duplicated and trace it back to the UI state that produced it.
Example fix
// before
payload = { notebookSorts: [...oldPositions, ...newPositions] }
// after
const seen = new Set()
payload = {
notebookSorts: [...oldPositions, ...newPositions]
.filter(item => {
if (seen.has(item.id)) return false
seen.add(item.id)
return true
})
} Defensive patterns
Strategy: validation
Validate before calling
// Deduplicate notebookSorts by ID before calling setFileTreeSort
function dedupeSortItems(items) {
const seen = new Set()
return items.filter(item => {
if (seen.has(item.id)) return false
seen.add(item.id)
return true
})
}
const cleanNotebookSorts = dedupeSortItems(notebookSorts) Prevention
- Always deduplicate sort item arrays by ID before sending to the kernel.
- In drag-and-drop handlers, remove the source item from its old position before inserting at the new position.
- Log the outgoing sort payload during development to catch duplicate IDs early.
When it happens
Trigger: Calling POST /api/filetree/setFileTreeSort with a notebookSorts array where two SortItem elements share the same id field (e.g. [{id:"202401010000-a",sort:1},{id:"202401010000-a",sort:2}]). Can also arise from a frontend bug that appends the same dragged notebook twice or fails to remove the original entry after a drag-and-drop reorder.
Common situations: Drag-and-drop reorder race in the file tree where the UI sends stale plus new positions for the same notebook; a plugin or external API client that constructs the sort payload by merging two lists without deduplication; concurrent sort operations from two browser tabs that both include the same notebook.
Related errors
- duplicate document ID [%s]
- notebook [%s] not found
- document [%s] not found in opened and unlocked notebooks
- block [%s] is not a sortable document
- assetPath is required for analyze
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/747d0456f2a758ce.
Report an issue: GitHub.