{"record":{"id":"d854e9d75e20021d","repo":"siyuan-note/siyuan","slug":"setting-or-removing-data-task-attribute-is-not-a","errorCode":null,"errorMessage":"setting or removing [data-task] attribute is not allowed via this interface. Please use \"/api/block/updateTaskListItemMarker\" or \"/api/block/batchUpdateTaskListItemMarker\" to update the task list item marker","messagePattern":"setting or removing \\[data-task\\] attribute is not allowed via this interface\\. Please use \"/api/block/updateTaskListItemMarker\" or \"/api/block/batchUpdateTaskListItemMarker\" to update the task list item marker","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/blockial.go","lineNumber":364,"sourceCode":"\tnewAttrsUnEsc := parse.IAL2MapUnEsc(node.KramdownIAL)\n\tfor name := range nameValues {\n\t\tif \"fold\" == strings.ToLower(name) {\n\t\t\tdelete(newAttrsUnEsc, \"heading-fold\")\n\t\t\tbreak\n\t\t}\n\t}\n\n\tfor name, value := range nameValues {\n\t\tvalue = util.RemoveInvalidRetainCtrl(value)\n\t\tvalue = strings.TrimSpace(value)\n\t\tlowerName := strings.ToLower(name)\n\t\t// 转换为小写再验证属性名\n\t\tif !isValidAttrName(lowerName) {\n\t\t\terr = errors.New(Conf.Language(25) + \" [\" + node.ID + \"]\")\n\t\t\treturn\n\t\t}\n\t\tif lowerName == \"data-task\" {\n\t\t\terr = errors.New(`setting or removing [data-task] attribute is not allowed via this interface. Please use \"/api/block/updateTaskListItemMarker\" or \"/api/block/batchUpdateTaskListItemMarker\" to update the task list item marker`)\n\t\t\treturn\n\t\t}\n\n\t\t// 处理文档标签 https://github.com/siyuan-note/siyuan/issues/13311\n\t\tif lowerName == \"tags\" {\n\t\t\tvar tags []string\n\t\t\ttmp := strings.SplitSeq(value, \",\")\n\t\t\tfor t := range tmp {\n\t\t\t\tt = strings.TrimSpace(t)\n\t\t\t\tif \"\" != t {\n\t\t\t\t\ttags = append(tags, t)\n\t\t\t\t}\n\t\t\t}\n\t\t\ttags = gulu.Str.RemoveDuplicatedElem(tags)\n\t\t\tif 0 < len(tags) {\n\t\t\t\tvalue = strings.Join(tags, \",\")\n\t\t\t} else {\n\t\t\t\tvalue = \"\"","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/blockial.go#L346-L382","documentation":"In setNodeAttrs0, after the attr-name check, if lowerName == 'data-task' the function hard-rejects with a message directing the caller to /api/block/updateTaskListItemMarker or /api/block/batchUpdateTaskListItemMarker. The data-task attribute encodes task-list-item state; setting it directly via the generic attr API would desync the list-item marker from the AST, so the kernel funnels all such changes through the dedicated marker endpoints.","triggerScenarios":"POST /api/attr/setBlockAttrs (or batchSetBlockAttrs, or MCP attr tool) with key 'data-task' on a task-list-item block, regardless of value (set or delete).","commonSituations":"A plugin toggling a checkbox by writing the IAL directly instead of using the marker API; generic 'set any attribute' tooling that does not special-case task state; copy of one block's full IAL onto another.","solutions":["Use POST /api/block/updateTaskListItemMarker {id, checked} for a single item, or /api/block/batchUpdateTaskListItemMarker for many.","Filter 'data-task' out of any generic attribute map before calling setBlockAttrs.","When copying block IAL wholesale, drop 'data-task' and re-apply it through the marker API."],"exampleFix":"// before\nfetchPost('/api/attr/setBlockAttrs', {id, attrs: {'data-task': 'todo'}})\n\n// after: use the dedicated task-list marker endpoint\nfetchPost('/api/block/updateTaskListItemMarker', {id, checked: false})","handlingStrategy":"validation","validationCode":"// Never let data-task reach the generic attr API.\ndelete(nameValues, \"data-task\")\nif taskWanted {\n    model.UpdateTaskListItemMarker(id, checked) // dedicated endpoint\n}","typeGuard":null,"tryCatchPattern":"// HTTP caller: on the explicit data-task rejection, call the marker API instead.\nif (r.code === -1 && r.msg.includes('data-task')) {\n    await fetchSyncPost('/api/block/updateTaskListItemMarker', {id, checked: value === 'todo'})\n}","preventionTips":["Always toggle checkbox state via updateTaskListItemMarker, never via setBlockAttrs.","When copying block IAL, drop 'data-task' and re-apply through the marker API."],"tags":["validation","attrs","task-list","api"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}