{"record":{"id":"4ef18fc14b7081ed","repo":"siyuan-note/siyuan","slug":"attribute-s-is-only-supported-on-regular-docume","errorCode":null,"errorMessage":"attribute [%s] is only supported on regular document roots","messagePattern":"attribute \\[(.+?)\\] is only supported on regular document roots","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/blockial.go","lineNumber":399,"sourceCode":"\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\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)","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/blockial.go#L381-L417","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nsetNodeAttrs(boxID, childBlockID, map[string]string{\"custom-sort\": \"3\"}) // error\n// after\nnode := treenode.GetNodeInTree(tree, id)\nif node != nil && ast.NodeDocument == node.Type && !IsBoxDoc(boxID, id) {\n    setNodeAttrs(boxID, id, map[string]string{\"custom-sort\": \"3\"})\n}","handlingStrategy":"validation","validationCode":"// TS: only set sort mode on regular document roots\nconst info = await fetchPost(\"/api/block/getBlockInfo\", { id });\nif (info.data.type !== \"NodeDocument\" || isEncryptedBox(info.data.box)) {\n  throw new Error(\"sort mode only on regular document roots\");\n}","typeGuard":"function isRegularDocRoot(info: { type: string; box: string }): boolean {\n  return info.type === \"NodeDocument\" && !isEncryptedBox(info.box);\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["doc-sort-mode","document-root","attribute-target"],"backgroundTag":"invalid-argument-value","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}