{"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":394,"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\t\tif DocSortModeAttr == lowerName {\n\t\t\tif ast.NodeDocument != node.Type || IsBoxDoc(boxID, node.ID) {\n\t\t\t\terr = fmt.Errorf(\"attribute [%s] is only supported on regular document roots\", DocSortModeAttr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif \"\" != value {\n\t\t\t\tsortMode, parseErr := strconv.Atoi(value)\n\t\t\t\tif nil != parseErr || !IsValidDocSortMode(sortMode) {\n\t\t\t\t\terr = fmt.Errorf(\"invalid document sort mode [%s]\", value)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tvalue = strconv.Itoa(sortMode)\n\t\t\t}\n\t\t}\n\n\t\t// 处理文档标签 https://github.com/siyuan-note/siyuan/issues/13311","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/blockial.go#L376-L412","documentation":"setNodeAttrs0 explicitly forbids writing the 'data-task' attribute through the generic attribute APIs, returning a fixed error directing callers to the dedicated task-marker endpoints. data-task is derived from task-list item markers, so direct mutation would desynchronize the attribute from the actual markdown checkbox state.","triggerScenarios":"POST /api/attr/setBlockAttrs or /api/attr/batchSetBlockAttrs (or any caller routing into setNodeAttrs0) with a key of 'data-task' (case-insensitive), on a task-list item block.","commonSituations":"Scripts trying to toggle todo state by editing data-task directly (e.g. moving items to 'done'); plugins syncing external task systems into SiYuan; automation migrating from older versions where direct attr writes worked.","solutions":["Call /api/block/updateTaskListItemMarker or /api/block/batchUpdateTaskListItemMarker instead to change task state","Skip/delete 'data-task' keys from batch payloads and handle them via the marker endpoint separately","If you just want to read task state, keep using the attribute but never write it through setBlockAttrs"],"exampleFix":"// before\nawait fetchPost('/api/attr/setBlockAttrs', {id, attrs: {'data-task': 'done'}});\n// after\nawait fetchPost('/api/block/updateTaskListItemMarker', {id: blockId, type: 't', data: 'x'});","handlingStrategy":"validation","validationCode":"if ('data-task' in attrs || Object.keys(attrs).some(k => k.toLowerCase() === 'data-task')) {\n  // route to /api/block/updateTaskListItemMarker instead\n}","typeGuard":"null","tryCatchPattern":"try { await setBlockAttrs(id, attrs); } catch (e) { if (String(e).includes('data-task')) { await updateTaskListItemMarker(id, 'x'); delete attrs['data-task']; await setBlockAttrs(id, attrs); } else throw e; }","preventionTips":["Never write data-task directly; always use the task-marker endpoints","Strip data-task from generic attr payloads before sending","Update task state via block marker updates so the attribute stays consistent","Check for the key case-insensitively (validation is case-insensitive)"],"tags":["siyuan","data-task","task-list","forbidden-attribute"],"backgroundTag":"operation-not-supported","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"}