siyuan-note/siyuan · error
source document [ ] not found
Error message
source document [%s] not found
What it means
Each source document is resolved with treenode.GetBlockTree and must be a sortable document, same as the target. If a source ID does not resolve to an existing document block, the whole reorder fails with this error before any change is applied. The check is all-or-nothing so a single bad ID aborts the batch.
Solutions
- Filter sourceIDs through an existence check (GetBlockTree equivalent / document listing) before calling the reorder API
- Refresh the UI tree and reselect the documents, then retry the reorder
- Identify the offending ID from the error message and remove it from the batch
- If IDs came from sync/queue state, wait for indexing to settle and rebuild the list
Example fix
// before reorderDocs(allIDs, targetID, "after") // after const valid = allIDs.filter(id => docExists(id)) reorderDocs(valid, targetID, "after")
Defensive patterns
Strategy: validation
Validate before calling
const existing = new Set((await listDocIDs(notebookId)))
const missing = sourceIDs.filter(id => !existing.has(id))
if (missing.length) throw new Error(`missing sources: ${missing.join(",")}`) Try / catch
try { await api.reorderDocs(src, targetID, pos) } catch (e) { if (String(e).includes("source document") && String(e).includes("not found")) { src = src.filter(docExists); return retryOnce() } throw e } Prevention
- Validate every source ID against a fresh document listing before batching
- Purge stale IDs from queues after sync deletions
- Fail fast per batch and report the exact offending ID to the user
When it happens
Trigger: Batch reorder call where one element of sourceIDs references a deleted/nonexistent document or a non-document block; stale IDs captured before a sync removed the documents.
Common situations: Plugins assembling source lists from stale UI selections; user deleting a document in another device/session then the local client attempting the queued reorder; concatenated IDs from different notebooks.
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
- target document [ ] not found
- block [ ] is not a document
- block [ ] is not a document that can declare a child…
- boot appearance not found
- ErrBlockNotFound
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/c3d5cd5ed408c78a.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/file.go:2698
ret = &ReorderResult{}
if err = validateReorderArgs(sourceIDs, targetID, position); nil != err {
return
}
FlushTxQueue()
target := treenode.GetBlockTree(targetID)
if !isSortableDocument(target) {
return ret, fmt.Errorf("target document [%s] not found", targetID)
}
box := Conf.Box(target.BoxID)
if nil == box {
return ret, fmt.Errorf("target document [%s] is not in an opened and unlocked notebook", targetID)
}
parentPath := path.Dir(target.Path)
for _, sourceID := range sourceIDs {
source := treenode.GetBlockTree(sourceID)
if !isSortableDocument(source) {
return ret, fmt.Errorf("source document [%s] not found", sourceID)
}
if source.BoxID != target.BoxID || path.Dir(source.Path) != parentPath {
return ret, fmt.Errorf("source document [%s] is not a sibling of target document [%s]", sourceID, targetID)
}
}
fileTreeSortLock.Lock()
confPath := filepath.Join(util.DataDir, box.ID, ".siyuan", "sort.json")
fullSortIDs, readErr := readSortConfMap(confPath)
if nil != readErr {
fileTreeSortLock.Unlock()
return ret, readErr
}
currentIDs, loadErr := loadSiblingCustomOrder(box.ID, parentPath, fullSortIDs)
if nil != loadErr {
fileTreeSortLock.Unlock()
return ret, loadErr
}View on GitHub (pinned to 9f775e8a12)