siyuan-note/siyuan · error
attribute [%s] is only supported on regular document roots
Error message
attribute [%s] is only supported on regular document roots
What it means
The doc-sort-mode attribute (DocSortModeAttr) may only be set on a genuine document root node, and never on a box-doc (encrypted notebook root). setNodeAttrs0 returns "attribute [%s] is only supported on regular document roots" when the target node is not ast.NodeDocument or is an encrypted box's document.
Source
Thrown at kernel/model/blockial.go:399
}
}
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
}
if DocSortModeAttr == lowerName {
if ast.NodeDocument != node.Type || IsBoxDoc(boxID, node.ID) {
err = fmt.Errorf("attribute [%s] is only supported on regular document roots", DocSortModeAttr)
return
}
if "" != value {
sortMode, parseErr := strconv.Atoi(value)
if nil != parseErr || !IsValidDocSortMode(sortMode) {
err = fmt.Errorf("invalid document sort mode [%s]", value)
return
}
value = strconv.Itoa(sortMode)
}
}
// 处理文档标签 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)View on GitHub (pinned to 8641553a1f)
Solutions
- Only set this attribute on the document root node (ast.NodeDocument) of a regular notebook
- Check IsBoxDoc / node type before issuing the update; skip encrypted-box documents
- Use the dedicated document sort API / UI to change sort mode instead of raw attributes
Example fix
// before
setNodeAttrs(boxID, childBlockID, map[string]string{"custom-sort": "3"}) // error
// after
node := treenode.GetNodeInTree(tree, id)
if node != nil && ast.NodeDocument == node.Type && !IsBoxDoc(boxID, id) {
setNodeAttrs(boxID, id, map[string]string{"custom-sort": "3"})
} Defensive patterns
Strategy: validation
Validate before calling
// TS: only set sort mode on regular document roots
const info = await fetchPost("/api/block/getBlockInfo", { id });
if (info.data.type !== "NodeDocument" || isEncryptedBox(info.data.box)) {
throw new Error("sort mode only on regular document roots");
} Type guard
function isRegularDocRoot(info: { type: string; box: string }): boolean {
return info.type === "NodeDocument" && !isEncryptedBox(info.box);
} Prevention
- Verify the target block is a document root before sort-mode writes
- Skip encrypted-notebook documents in sort-mode automation
- Prefer the dedicated sort-mode API/UI over raw attribute writes
When it happens
Trigger: Setting the doc sort mode attribute via setNodeAttrs / BatchSetBlockAttrs on a non-document block (child block) or on a document inside an encrypted notebook (IsBoxDoc true).
Common situations: Plugins applying sort-mode attributes to ordinary blocks by mistake; scripts iterating all blocks and setting sort mode on each; sort-mode attempts on encrypted notebook docs.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4ef18fc14b7081ed.
Report an issue: GitHub.