{"record":{"id":"c84da79ce9d89838","repo":"siyuan-note/siyuan","slug":"attribute-view-rich-text-tree-is-missing","errorCode":null,"errorMessage":"attribute view rich text tree is missing","messagePattern":"attribute view rich text tree is missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/av/value.go","lineNumber":592,"sourceCode":"\t}\n\tblockDOM, tree = luteEngine.Md2BlockDOMTree(content, true)\n\tif nil == tree || nil == tree.Root {\n\t\terr = fmt.Errorf(\"parse attribute view rich text failed\")\n\t\treturn\n\t}\n\tif 0 < len(protectedStyleEntities) {\n\t\tif err = restoreValueTextRichTreeStyleEntities(tree, protectedStyleEntities); nil != err {\n\t\t\treturn\n\t\t}\n\t\tblockDOM = luteEngine.Tree2BlockDOM(tree, luteEngine.RenderOptions, luteEngine.ParseOptions)\n\t}\n\terr = validateValueTextRichTree(tree)\n\treturn\n}\n\nfunc validateValueTextRichTree(tree *parse.Tree) (err error) {\n\tif nil == tree || nil == tree.Root {\n\t\treturn fmt.Errorf(\"attribute view rich text tree is missing\")\n\t}\n\tast.Walk(tree.Root, func(node *ast.Node, entering bool) ast.WalkStatus {\n\t\tif !entering {\n\t\t\treturn ast.WalkContinue\n\t\t}\n\t\tif !isAllowedValueTextRichNode(node) {\n\t\t\terr = fmt.Errorf(\"unsupported attribute view rich text node [%s]\", node.Type.String())\n\t\t\treturn ast.WalkStop\n\t\t}\n\t\treturn ast.WalkContinue\n\t})\n\treturn\n}\n\n// newValueTextRichLute 固定启用存储格式支持的语法，避免编辑器开关变化后重解释既有数据。\nfunc newValueTextRichLute() *lute.Lute {\n\tret := lute.New()\n\tret.SetTextMark(true)","sourceCodeStart":574,"sourceCodeEnd":610,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/av/value.go#L574-L610","documentation":"validateValueTextRichTree guards the DOM tree produced from rich-text content: a nil tree or nil root is reported as \"attribute view rich text tree is missing\". It is the entry-point check of the tree validator used by parseValueTextRich and RenderValueTextRich before walking nodes.","triggerScenarios":"RenderValueTextRich called with a nil tree argument, or parseValueTextRich somehow proceeding with a degenerate parse result (nil tree/root). Callers pass a parse.Tree that failed to materialize.","commonSituations":"Plugin code calling RenderValueTextRich directly with an uninitialized tree; callers skipping parseValueTextRich's earlier nil-tree error path; mocked trees in tests left nil.","solutions":["Ensure the tree comes from parseValueTextRich (or Md2BlockDOMTree) rather than being constructed ad hoc","Check for and handle the parse error from ParseValueTextRich before calling RenderValueTextRich","Initialize the tree properly in tests/plugin code before validation","Fix the underlying content issue (see error 235) so parsing yields a real root"],"exampleFix":"// before\nvar tree *parse.Tree\nerr = validateValueTextRichTree(tree) // nil tree\n// after\ntree := luteEngine.Md2BlockDOMTree(content, true)\nerr = validateValueTextRichTree(tree)","handlingStrategy":"type-guard","validationCode":"if tree == nil || tree.Root == nil { return errors.New(\"tree not parsed\") }","typeGuard":"func hasRoot(tree *parse.Tree) bool { return tree != nil && tree.Root != nil }","tryCatchPattern":"if err := av.RenderValueTextRich(tree); err != nil { /* handle missing-tree case */ }","preventionTips":["Always derive trees from ParseValueTextRich, never construct by hand","Check the parse error before using the returned tree","Initialize test fixtures with real parsed trees"],"tags":["attribute-view","rich-text","null-tree","validation"],"backgroundTag":"internal-invariant-violation","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"}