{"record":{"id":"84fc50895405b91c","repo":"siyuan-note/siyuan","slug":"task-list-item-marker-not-found","errorCode":null,"errorMessage":"task list item marker not found","messagePattern":"task list item marker not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/block_op.go","lineNumber":84,"sourceCode":"\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\n\n\ttreenode.RefreshUpdated(li)\n\n\treturn luteEngine.RenderNodeBlockDOM(li), nil\n}\n\nfunc updateTaskListItemMarker(c *gin.Context) {\n\tret := gulu.Ret.NewResult()\n\tdefer c.JSON(http.StatusOK, ret)\n\n\targ, ok := util.JsonArg(c, ret)\n\tif !ok {\n\t\treturn\n\t}","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/api/block_op.go#L66-L102","documentation":"Returned when the loaded list-item node has no child of type ast.NodeTaskListItemMarker. The kernel treats ListData.Typ==3 as a task list item, but the actual checkbox marker sub-node (the `[x]`/`[ ]` glyph holder) is missing from the tree — usually indicating data corruption or a hand-edited/malformed .sy file rather than an API misuse.","triggerScenarios":"POST /api/block/updateTaskListItemMarker on a node whose ListData.Typ==3 passed the earlier guard but whose children do not include a NodeTaskListItemMarker. This arises with manually constructed/edited trees, partially migrated blocks, or blocks produced by older versions that did not always emit the marker child.","commonSituations":"Notebooks imported from Markdown where the importer set Typ=3 but did not synthesize the marker child. Direct .sy file editing or external sync tools that stripped child nodes. Bugs in custom block-generation code that sets ListData.Typ=3 without appending a NodeTaskListItemMarker child (see transaction_list_item_fold_test.go:19 for the correct construction pattern).","solutions":["Inspect the block's .sy file / use /api/block/getBlockKramdown to confirm the node structure is intact.","If the block is malformed, recreate the task list item in the editor so the kernel regenerates the marker child node.","In programmatic node construction, always append a NodeTaskListItemMarker child when setting ListData.Typ=3 (mirror the test pattern).","Guard callers to skip blocks where ChildByType(NodeTaskListItemMarker) is nil instead of treating them as toggleable."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// Fetch block kramdown and check it contains a task marker before toggling\nconst kd = await getBlockKramdown(id);\nif (!/\\[[ xX]\\]/.test(kd)) { throw new Error('block has no task marker child; recreate it'); }","typeGuard":"// Structural guard: only treat as toggleable when a marker child exists\nfunction isToggleableTaskItem(node): node is TaskItem {\n  return node?.ListData?.Typ === 3 && node.children?.some(c => c.Type === 'NodeTaskListItemMarker');\n}","tryCatchPattern":"try { await updateTaskMarker(id, marker); }\ncatch (e) { if (/marker not found/.test(e.msg)) { /* recreate block via editor, skip */ } else throw e; }","preventionTips":["When building task items programmatically, always append a NodeTaskListItemMarker child (see transaction_list_item_fold_test.go).","Periodically validate notebook tree integrity for encrypted/imported data.","Skip blocks whose tree lacks the marker rather than assuming toggle works."],"tags":["api","task-list","data-integrity","kernel"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}