siyuan-note/siyuan · error

block is not a list item

Error message

block is not a list item

What it means

After fetching the block, buildUpdatedTaskListItemBlockDOM requires block.Type == "NodeListItem"; any other block type (paragraph, heading, etc.) makes the task-list-item DOM update meaningless, so it fails with this error.

Solutions

  1. Pass the NodeListItem block's ID, not a child node's ID
  2. Re-read the block's type via /api/filetree/getDoc or getBlockInfo and route non-item blocks elsewhere
  3. If the item lost its task marker, re-apply the task formatting first

Example fix

// before
updateTaskItem(childParagraphId)
// after
const parentId = block.parentID // NodeListItem
updateTaskItem(parentId)
Defensive patterns

Strategy: validation

Validate before calling

const info = await fetchPost('/api/block/getBlockInfo', {id});
if (info.data.type !== 'NodeListItem') throw new Error('not a list item');

Type guard

const isListItem = (b) => b?.type === 'NodeListItem';

Try / catch

try { await updateTaskItem(id, marker) } catch (e) { if (String(e).includes('not a list item')) await redirectToGenericBlockUpdate(id) }

Prevention

When it happens

Trigger: Calling the task list item update operation with a block ID that resolves to a non-list-item block, e.g. a paragraph inside a task item rather than the item itself.

Common situations: Client grabbing the inner text block's ID instead of the li block ID; document structure changed (task marker removed) so the block is now a plain paragraph; plugin assumptions about older content.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/289580e315e1092e. Report an issue: GitHub.

Appendix: source

Thrown at kernel/api/block_op.go:41

	"github.com/88250/gulu"
	"github.com/88250/lute"
	"github.com/88250/lute/ast"
	"github.com/gin-gonic/gin"
	"github.com/siyuan-note/siyuan/kernel/apicontract"
	"github.com/siyuan-note/siyuan/kernel/filesys"
	"github.com/siyuan-note/siyuan/kernel/model"
	"github.com/siyuan-note/siyuan/kernel/treenode"
	"github.com/siyuan-note/siyuan/kernel/util"
)

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

View on GitHub (pinned to 9f775e8a12)