siyuan-note/siyuan · error

document [ ] not found in opened and unlocked notebooks

Error message

document [%s] not found in opened and unlocked notebooks

What it means

A sort item must reference a sortable document: its block-tree record must be a root node (bt.ID == bt.RootID) of type "d" and must not itself be the notebook's box doc entry (IsBoxDoc). Otherwise the kernel rejects it with "block [%s] is not a sortable document". This prevents attempts to reorder headings, child blocks, or virtual box-level entries.

Solutions

  1. Use the document's root ID (RootID from the block tree / the .sy filename) instead of an inner block ID
  2. Only sort documents that appear as siblings under a parent path in a notebook; child blocks cannot be reordered via this API
  3. Filter the sort list to items whose block-tree type is "d" and whose ID equals RootID

Example fix

// before: heading block ID passed in
sortDocs(["20240101120000-abcdefgh"])
// after: resolve to the document root
const rootId = getBlockTree(blockId).root_id;
sortDocs([rootId])
Defensive patterns

Strategy: type-guard

Validate before calling

const bt = await api.getBlockTree(id);
if (!bt || bt.id !== bt.root_id || bt.type !== 'd') throw new Error('not a sortable document root');

Type guard

const isDocRoot = (bt) => bt != null && bt.id === bt.root_id && bt.type === 'd';

Try / catch

try { await api.sortDocs(items); } catch (e) { if (String(e).includes('is not a sortable document')) { const roots = items.map(i => toRootId(i.id)); await api.sortDocs(roots); } else { throw e; } }

Prevention

When it happens

Trigger: Passing a non-root block ID (heading, paragraph, child document in a doc tree), a container/attribute-view block type other than "d", or the box's internal doc ID into the document sort API.

Common situations: Client bug using selected-block IDs instead of the document root ID; attempting to sort child documents of a document tree (which are regular blocks, not siblings under a parent path); scripting against exported IDs that point at headings.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/f6adcad15020e923. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/file.go:2936

			return ret, fmt.Errorf("notebook [%s] not found", item.ID)
		}
		notebookPlans = append(notebookPlans, &notebookSortPlan{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, readErr

View on GitHub (pinned to 9f775e8a12)