siyuan-note/siyuan · error
setting or removing [data-task] attribute is not allowed via
Error message
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
What it means
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.
Source
Thrown at kernel/model/blockial.go:364
newAttrsUnEsc := parse.IAL2MapUnEsc(node.KramdownIAL)
for name := range nameValues {
if "fold" == strings.ToLower(name) {
delete(newAttrsUnEsc, "heading-fold")
break
}
}
for name, value := range nameValues {
value = util.RemoveInvalidRetainCtrl(value)
value = strings.TrimSpace(value)
lowerName := strings.ToLower(name)
// 转换为小写再验证属性名
if !isValidAttrName(lowerName) {
err = errors.New(Conf.Language(25) + " [" + node.ID + "]")
return
}
if lowerName == "data-task" {
err = 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`)
return
}
// 处理文档标签 https://github.com/siyuan-note/siyuan/issues/13311
if lowerName == "tags" {
var tags []string
tmp := strings.SplitSeq(value, ",")
for t := range tmp {
t = strings.TrimSpace(t)
if "" != t {
tags = append(tags, t)
}
}
tags = gulu.Str.RemoveDuplicatedElem(tags)
if 0 < len(tags) {
value = strings.Join(tags, ",")
} else {
value = ""View on GitHub (pinned to 251596fc0d)
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.
Example fix
// before
fetchPost('/api/attr/setBlockAttrs', {id, attrs: {'data-task': 'todo'}})
// after: use the dedicated task-list marker endpoint
fetchPost('/api/block/updateTaskListItemMarker', {id, checked: false}) Defensive patterns
Strategy: validation
Validate before calling
// Never let data-task reach the generic attr API.
delete(nameValues, "data-task")
if taskWanted {
model.UpdateTaskListItemMarker(id, checked) // dedicated endpoint
} Try / catch
// HTTP caller: on the explicit data-task rejection, call the marker API instead.
if (r.code === -1 && r.msg.includes('data-task')) {
await fetchSyncPost('/api/block/updateTaskListItemMarker', {id, checked: value === 'todo'})
} Prevention
- Always toggle checkbox state via updateTaskListItemMarker, never via setBlockAttrs.
- When copying block IAL, drop 'data-task' and re-apply through the marker API.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- task list item marker length should be 1
- task list item marker can not be [ or ]
- task list item marker not found
- custom emoji file is too large
- custom emoji file must not be empty
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/d854e9d75e20021d.
Report an issue: GitHub.