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

  1. Filter sourceIDs through an existence check (GetBlockTree equivalent / document listing) before calling the reorder API
  2. Refresh the UI tree and reselect the documents, then retry the reorder
  3. Identify the offending ID from the error message and remove it from the batch
  4. 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

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


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)