{"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":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/block_op.go","lineNumber":69,"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\nvar updateTaskListItemMarker = contractHandler(apicontract.UpdateTaskListItemMarker, func(c *gin.Context, request apicontract.TaskListMarkerRequest) apicontract.Response[[]*apicontract.BlockTransaction] {\n\tret := gulu.Ret.NewResult()\n\n\tid, marker := request.ID, request.Marker\n\tif util.InvalidIDPattern(id, ret) {\n\t\treturn contractFailure[[]*apicontract.BlockTransaction](ret)\n\t}\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/api/block_op.go#L51-L87","documentation":"After validating the ID and marker, buildUpdatedTaskListItemBlockDOM looks for the list item's ast.NodeTaskListItemMarker child node — the AST node that physically carries the checkbox. If the node has no such child (its ListData.Typ said task item, but no marker node exists in this serialization), the function cannot apply the change and errors out. This signals a structurally inconsistent or corrupted list item in the .sy tree.","triggerScenarios":"Calling the marker update API on a task list item whose stored AST lacks the NodeTaskListItemMarker child — e.g. after a malformed paste/conversion, an external edit of the .sy file, a lute version change in serialization, or document corruption after a failed sync.","commonSituations":"Documents edited by external tools or older/newer SiYuan versions writing inconsistent ASTs; corrupted .sy content after sync conflicts; a node created programmatically as Typ 3 without the marker child.","solutions":["Re-render/re-save the affected block in the editor (edit the item, toggle it manually) to let lute normalize the AST, then retry the API call","Inspect the .sy file JSON for the block and confirm whether TaskListItemMarker exists; fix or recreate the list item if it is missing","Restore the document from SiYuan history (Data history / snapshot) if the block was corrupted by sync or an external edit","Rebuild the index; if the on-disk tree itself is malformed, re-export/re-paste the list content into a fresh block"],"exampleFix":"// before: blindly updating a possibly-corrupt item\nawait fetchPost('/api/block/updateTaskListItemMarker', { id, marker: 'x' });\n// after: verify the item renders as a task item first, and recreate it if not\nconst dom = await fetchPost('/api/filetree/getDoc', { id });\nif (!dom.content.includes('data-task')) {\n  await recreateTaskListItem(id); // re-insert the item via insertBlock so lute rebuilds the marker node\n}\nawait fetchPost('/api/block/updateTaskListItemMarker', { id, marker: 'x' });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await fetchPost('/api/block/updateTaskListItemMarker', { id, marker });\n} catch (e) {\n  if (String(e?.msg).includes('task list item marker not found')) {\n    // AST is inconsistent: recreate the item or restore from history instead of retrying\n    await recreateBlockFromHistory(id);\n  } else { throw e; }\n}","preventionTips":["Do not edit .sy files with external tools; only mutate documents through SiYuan","Keep all clients on the same SiYuan version to avoid AST serialization drift","After failed syncs, verify affected documents render correctly before scripting against them","Take snapshots before programmatic bulk edits so blocks can be restored"],"tags":["blocks","ast","corruption","siyuan","task-list"],"backgroundTag":"internal-invariant-violation","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"}