siyuan-note/siyuan · error

get block failed: %s

Error message

get block failed: %s

What it means

First failure mode of buildUpdatedTaskListItemBlockDOM (kernel/api/block_op.go), which backs POST /api/block/updateTaskListItemMarker and its batch variant. The block id passed format validation (InvalidIDPattern) but model.GetBlock failed at the SQL layer; the underlying error text is appended after the prefix, so the real cause (query failure, unavailable/corrupt index) rides along in the message.

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

Solutions

  1. Verify the id first with /api/block/getBlockInfo (or getBlockKramdown) to see whether the block is queryable at all
  2. Wait for indexing/sync to quiesce (check the status via the kernel UI/status API) and retry the call
  3. If the block genuinely exists on disk, trigger a rebuild of the content index so the blocks table is repopulated
  4. Inspect the appended underlying error and the kernel log; if siyuan.db is corrupt, restore the workspace from backup or repo snapshot
Defensive patterns

Strategy: try-catch

Validate before calling

const info = await fetchPost('/api/block/getBlockInfo', { id });
if (info.code !== 0) {
  throw new Error(`block [${id}] not queryable, skip marker update`);
}
await fetchPost('/api/block/updateTaskListItemMarker', { id, marker });

Try / catch

try {
  await updateTaskMarker(id, marker);
} catch (e) {
  if (/^get block failed:/.test(e.message)) {
    const cause = e.message.slice('get block failed:'.length).trim();
    // index/db level: wait for indexing to settle, verify block exists, then retry once
  }
}

Prevention

When it happens

Trigger: Calling /api/block/updateTaskListItemMarker with an id that is well-formed but absent from or broken in the SQL index (siyuan.db); calling while the database is locked by indexing, sync, or another heavy transaction; calling right after workspace corruption or an interrupted reindex.

Common situations: Stale block id captured before a rebuild; kernel mid-reindex or sync so the blocks table is inconsistent; siyuan.db corrupted after a crash or bad shutdown; plugin cached ids across workspace switches.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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