{"record":{"id":"68fd965df3880661","repo":"siyuan-note/siyuan","slug":"block-is-not-a-task-list-item","errorCode":null,"errorMessage":"block is not a task list item","messagePattern":"block is not a task list item","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/block_op.go","lineNumber":55,"sourceCode":"\t\treturn \"\", errors.New(\"get block failed: \" + err.Error())\n\t}\n\n\tif \"NodeListItem\" != block.Type {\n\t\treturn \"\", errors.New(\"block is not a list item\")\n\t}\n\n\ttree, err := filesys.LoadTree(block.Box, block.Path, luteEngine)\n\tif err != nil {\n\t\treturn \"\", errors.New(\"load tree failed: \" + err.Error())\n\t}\n\n\tli := treenode.GetNodeInTree(tree, id)\n\tif li == nil {\n\t\treturn \"\", errors.New(\"block not found\")\n\t}\n\n\tif 3 != li.ListData.Typ {\n\t\treturn \"\", errors.New(\"block is not a task list item\")\n\t}\n\n\tif 1 != len(marker) {\n\t\treturn \"\", errors.New(\"task list item marker length should be 1\")\n\t}\n\n\tliMarker := marker[0]\n\tif '[' == liMarker || ']' == liMarker {\n\t\treturn \"\", errors.New(\"task list item marker can not be [ or ]\")\n\t}\n\n\tmarkerNode := li.ChildByType(ast.NodeTaskListItemMarker)\n\tif nil == markerNode {\n\t\treturn \"\", errors.New(\"task list item marker not found\")\n\t}\n\n\tmarkerNode.TaskListItemMarker = liMarker\n\tmarkerNode.TaskListItemChecked = ' ' != markerNode.TaskListItemMarker","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/api/block_op.go#L37-L73","documentation":"The updateTaskListItemMarker endpoint only operates on task list items (list nodes with ListData.Typ == 3). buildUpdatedTaskListItemBlockDOM found the node in the tree, but it is a regular ordered/bullet list item, not a task item, so it refuses to apply a checkbox marker. This is a type guard, not a state problem.","triggerScenarios":"Passing the ID of a bullet list item (ListData.Typ == 0), an ordered list item (Typ == 1), or any non-list node (paragraph, heading, etc.) to POST /api/block/updateTaskListItemMarker or batchUpdateTaskListItemMarker.","commonSituations":"A plugin queries blocks WHERE type='l' but the matching item is a plain bullet list; UI selection grabbed the wrong node; content was converted from task item to bullet item by an earlier edit so a cached ID now points at a non-task item.","solutions":["Filter your block query to task list items only, e.g. subtype='t' on l blocks (SELECT id FROM blocks WHERE type='l' AND subtype='t')","Check the returned block type/subtype with /api/query/sql before calling the marker API","Convert the target to a task list item in the editor first, or use a generic block update operation instead of the marker-specific endpoint","If you need to toggle markers in bulk, verify each item's subtype in the batch loop and skip non-task items"],"exampleFix":"// before\nconst blocks = await sql(\"SELECT id FROM blocks WHERE type='l' AND content LIKE '%TODO%'\");\n// after\nconst blocks = await sql(\"SELECT id FROM blocks WHERE type='l' AND subtype='t' AND content LIKE '%TODO%'\");","handlingStrategy":"validation","validationCode":"const rows = await fetchPost('/api/query/sql', { stmt: `SELECT subtype FROM blocks WHERE id='${id}'` });\nif (!rows.length || rows[0].subtype !== 't') throw new Error(`block ${id} is not a task list item`);","typeGuard":"const isTaskListItem = (b) => !!b && b.type === 'l' && b.subtype === 't';","tryCatchPattern":"try {\n  return await fetchPost('/api/block/updateTaskListItemMarker', { id, marker });\n} catch (e) {\n  if (typeof e?.msg === 'string' && e.msg.includes('not a task list item')) {\n    console.warn(`Skipping non-task list item ${id}`);\n    return null; // skip, don't crash the batch\n  }\n  throw e;\n}","preventionTips":["Filter SQL queries with subtype='t' when targeting task items","Check block.type/subtype before calling marker-specific APIs","Re-validate item types after content edits that can convert list kinds"],"tags":["blocks","type-mismatch","siyuan","task-list"],"backgroundTag":"incompatible-source-type","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}