siyuan-note/siyuan · error

get block failed:

Error message

get block failed: 

What it means

buildUpdatedTaskListItemBlockDOM wraps any error from model.GetBlock(id, nil) with the prefix "get block failed: ". model.GetBlock fails when the block ID cannot be resolved to a row in the blocks index (blocktree), meaning the ID does not exist, is stale, or the notebook is unavailable. The kernel throws this while updating a task list item checkbox because the target list item could not be loaded.

Source

Thrown at kernel/api/block_op.go:52

func parseBlockUpdateInput(arg map[string]any, ret *gulu.Result) (input model.BlockUpdateInput, ok bool) {
	if !util.ParseJsonArgs(arg, ret,
		util.BindJsonArg("id", &input.ID, true, true),
		util.BindJsonArg("data", &input.Data, true, false),
		util.BindJsonArg("dataType", &input.DataType, true, true),
		util.BindJsonArg("lockType", &input.LockType, false, false),
	) {
		return
	}
	if util.InvalidIDPattern(input.ID, ret) {
		return input, false
	}
	return input, true
}

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")

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Re-fetch the block/tree on the frontend (getBlockByID / reload the document) and retry with a fresh ID
  2. Verify the ID exists via the kernel API /api/query/sql or getBlockInfo before calling the marker update
  3. Check the ID string is a valid 22-char SiYuan block ID with no whitespace or trimming issues
  4. If IDs are systematically stale, reindex the notebook (Rebuild Index) so blocktree matches disk

Example fix

// before
updateTaskListItemMarker(staleId, "x", cb);
// after
const info = await fetchSyncPost("/api/filetree/getDocInfo", { id: staleId });
if (!info || info.code !== 0) { reloadDoc(); return; }
updateTaskListItemMarker(staleId, "x", cb);
Defensive patterns

Strategy: validation

Validate before calling

const info = await fetchSyncPost("/api/block/getBlockInfo", { id });
if (info.code !== 0) { /* skip or reload */ }

Try / catch

try { await updateTaskListItemMarker(id, "x"); } catch (e) { if (String(e).includes("get block failed")) { reloadDoc(); } }

Prevention

When it happens

Trigger: Calling updateTaskListItemMarker or batchUpdateTaskListItemMarker (task checkbox toggle API path) with a block ID that is absent from the in-memory block tree: the document was re-indexed, the block was deleted, the ID is malformed, or the blocktree cache is stale.

Common situations: Frontend holds a stale block ID after another client synced deletions; plugin passes an arbitrary string instead of a real .sy block ID; concurrent transaction removed the list item between rendering and checkbox click; notebook not yet indexed after open.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/a90a28052157a02e. Report an issue: GitHub.