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

  1. Only set this attribute on the document root node (ast.NodeDocument) of a regular notebook
  2. Check IsBoxDoc / node type before issuing the update; skip encrypted-box documents
  3. 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

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.