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

  1. Retry after a short delay — if it is index lag, the flush (FlushTxQueue) will reconcile the tree and index
  2. Verify with /api/block/getBlockInfo which rootID/path the index currently claims, and open that document to confirm the block exists
  3. Trigger a reindex of the affected notebook so index and trees reconverge
  4. 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

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


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/07f4fc6f49446008. Report an issue: GitHub.