siyuan-note/siyuan · error

block [%s] is not a document

Error message

block [%s] is not a document

What it means

In GetDocBlocksOrders (blockinfo.go:558), after the tree for id is loaded and confirmed non-nil, the function checks tree.Root.ID != id and if so returns fmt.Errorf('block [%s] is not a document', id). This walker (getDocBlocksOrdersInTree) returns the ordered list of child block ids under a document root, so it must be given a document (root) id; passing any non-root block id is a caller error, not a data problem. ErrTreeNotFound is returned separately when the tree itself is missing.

Source

Thrown at kernel/model/blockinfo.go:569

	for _, id := range ids {
		ret[id] = nodesIndexes[id]
	}
	return
}

func GetDocBlocksOrders(id string) (ret []string, err error) {
	ret = []string{}
	tree, err := LoadTreeByBlockID(id)
	if err != nil {
		return
	}
	if nil == tree || nil == tree.Root {
		err = ErrTreeNotFound
		return
	}
	if tree.Root.ID != id {
		err = fmt.Errorf("block [%s] is not a document", id)
		return
	}

	ret = getDocBlocksOrdersInTree(tree)
	return
}

func getDocBlocksOrdersInTree(tree *parse.Tree) (ret []string) {
	ret = []string{}
	ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
		if !entering || n == tree.Root || !n.IsBlock() || ast.NodeKramdownBlockIAL == n.Type || "" == n.ID {
			return ast.WalkContinue
		}

		ret = append(ret, n.ID)
		return ast.WalkContinue
	})
	return

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Resolve the id to its document root first via /api/block/getBlockInfo (rootID field) and pass that.
  2. On the client, derive the doc id from the open editor document rather than from the current selection.
  3. If you only have a child id, walk up: childID -> blockInfo.rootID -> getDocBlocksOrders(rootID).

Example fix

// before
orders, err := model.GetDocBlocksOrders(childID)

// after: resolve to the document root first
rootID := treenode.GetBlockTree(childID).RootID
orders, err := model.GetDocBlocksOrders(rootID)
Defensive patterns

Strategy: validation

Validate before calling

// Resolve a child id to its document root before asking for block orders.
bt := treenode.GetBlockTree(id)
docID := id
if bt != nil { docID = bt.RootID }
model.GetDocBlocksOrders(docID)

Try / catch

// HTTP caller: on 'is not a document', resolve rootID and retry.
let r = await fetchSyncPost('/api/block/getDocBlocksOrders', {id})
if (r.code === -1 && /not a document/i.test(r.msg)) {
    const info = await fetchSyncPost('/api/block/getBlockInfo', {id})
    r = await fetchSyncPost('/api/block/getDocBlocksOrders', {id: info.data.rootID})
}

Prevention

When it happens

Trigger: POST /api/block/getDocBlocksOrders {id} with the id of a paragraph, heading, list, list-item, embed, or any other non-document block instead of the document root id.

Common situations: Caller confuses a block id with its document id; passes a selection/focus id straight through; copies a child id from a ref instead of resolving it to its root.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/d70b8b7912c59283. Report an issue: GitHub.