siyuan-note/siyuan · error
block not found
Error message
block not found
What it means
Thrown by buildUpdatedTaskListItemBlockDOM (kernel/api/block_op.go) when the .sy tree loads successfully but treenode.GetNodeInTree cannot find a node with the given id inside it. The SQL index believes the block lives in this document, but the in-memory tree disagrees — an index/tree desynchronization, not a bad file.
Source
Thrown at kernel/api/block_op.go:66
func buildUpdatedTaskListItemBlockDOM(id, marker string, luteEngine *lute.Lute) (data string, err error) {
block, err := model.GetBlock(id, nil)
if err != nil {
return "", errors.New("get block failed: " + err.Error())
}
if "NodeListItem" != block.Type {
return "", errors.New("block is not a list item")
}
tree, err := filesys.LoadTree(block.Box, block.Path, luteEngine)
if err != nil {
return "", errors.New("load tree failed: " + err.Error())
}
li := treenode.GetNodeInTree(tree, id)
if li == nil {
return "", errors.New("block not found")
}
if 3 != li.ListData.Typ {
return "", errors.New("block is not a task list item")
}
if 1 != len(marker) {
return "", errors.New("task list item marker length should be 1")
}
liMarker := marker[0]
if '[' == liMarker || ']' == liMarker {
return "", errors.New("task list item marker can not be [ or ]")
}
markerNode := li.ChildByType(ast.NodeTaskListItemMarker)
if nil == markerNode {
return "", errors.New("task list item marker not found")View on GitHub (pinned to afa823b6b4)
Solutions
- Retry after a short delay — if it is index lag, the flush (FlushTxQueue) will reconcile the tree and index
- Verify with /api/block/getBlockInfo which rootID/path the index currently claims, and open that document to confirm the block exists
- Trigger a reindex of the affected notebook so index and trees reconverge
- If the block was truly deleted, discard the stale id and stop updating it
Defensive patterns
Strategy: validation
Validate before calling
const info = await fetchPost('/api/block/getBlockInfo', { id });
if (info.code !== 0) throw new Error('block unknown to index');
const root = info.data.root_id;
// confirm the doc still contains the block before mutating
const doc = await fetchPost('/api/filetree/getDoc', { id: root });
if (!doc.data?.includes?.(id)) throw new Error('stale block id'); Type guard
const isLiveBlockId = (id: string, docContent: string): boolean => docContent.includes(`"${id}"`); Try / catch
if (e.message === 'block not found') {
// index/tree mismatch: wait one flush interval, re-fetch block info, retry once; else drop the id
} Prevention
- Treat captured block ids as ephemeral; re-verify before use
- Retry once after FlushTxQueue settles — most cases are async-index lag
- Reindex the notebook when mismatches persist
When it happens
Trigger: The block was moved or deleted in the editor while its SQL index row was not yet updated (async indexing lag); a transaction failed halfway leaving index and document inconsistent; the same block id is referenced from a different document than the one indexed; workspace restored partially so index and .sy files diverge.
Common situations: Rapid successive edits where the API is called between the write and the index flush; kernel killed before the async index queue drained; sync conflicts resolved by keeping one side's .sy but the other side's index; plugin holds ids longer than the document lifetime.
Related errors
- get block failed: %s
- block is not a list item
- block is not a task list item
- Content block with id [%s] not found
- block updates are empty
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/07f4fc6f49446008.
Report an issue: GitHub.