{"record":{"id":"6b7c3f1b085d861d","repo":"siyuan-note/siyuan","slug":"tree-is-empty","errorCode":null,"errorMessage":"tree is empty","messagePattern":"tree is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/filesys/tree.go","lineNumber":229,"sourceCode":"\t\treturn\n\t}\n\n\tret, err = LoadTreeByData(data, boxID, p, luteEngine)\n\tif nil == err {\n\t\tcache.SetTreeDataInBox(rootID, boxID, data)\n\t}\n\treturn\n}\n\nfunc LoadTree(boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err error) {\n\tret, _, err = LoadTreeWithFix(boxID, p, luteEngine)\n\treturn\n}\n\n// NormalizeTreeForRead 对只读树应用与文件加载一致的规范化处理，但不写回磁盘。\nfunc NormalizeTreeForRead(tree *parse.Tree) (err error) {\n\tif nil == tree || nil == tree.Root {\n\t\treturn errors.New(\"tree is empty\")\n\t}\n\tif err = treenode.CheckSpec(tree); nil != err {\n\t\treturn\n\t}\n\tif err = treenode.RefreshTableCellRichProjection(tree.Root); nil != err {\n\t\treturn\n\t}\n\ttreenode.UpgradeSpec(tree)\n\tescapeAttributeValues(tree)\n\treturn\n}\n\nfunc LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err error) {\n\tret, err = parseJSON2Tree(boxID, p, data, luteEngine)\n\tif nil != err {\n\t\tlogging.LogErrorf(\"parse tree [%s] failed: %s\", p, err)\n\t\treturn\n\t}","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/filesys/tree.go#L211-L247","documentation":"NormalizeTreeForRead applies load-time normalization to a parsed tree without writing back. It first checks that the tree and its Root are non-nil and returns this error when the caller handed it an empty/unparsed tree. It is an input-state guard, not a disk problem.","triggerScenarios":"Calling NormalizeTreeForRead with nil, with a parse.Tree whose Root is nil (e.g. lute parse failed or produced an empty tree), or with a zero-value struct.","commonSituations":"Parsing an empty or corrupted .sy file whose tree has no root; calling the API on a tree you constructed yourself but never populated; an upstream parse step silently failing and the nil tree being propagated.","solutions":["Check the tree was actually parsed (parse the .sy content with lute) before normalizing.","Verify the source file is non-empty and valid JSON .sy content.","Guard the call site: skip normalization when tree == nil || tree.Root == nil."],"exampleFix":"// before\nNormalizeTreeForRead(tree)\n// after\nif tree == nil || tree.Root == nil {\n    return errors.New(\"tree was not parsed\")\n}\nNormalizeTreeForRead(tree)","handlingStrategy":"type-guard","validationCode":"if (tree == null || tree.Root == null) { /* parse first or abort */ }","typeGuard":"func hasRoot(t *parse.Tree) bool { return t != nil && t.Root != nil }","tryCatchPattern":"if err := filesys.NormalizeTreeForRead(tree); err != nil {\n    // tree empty or spec check failed; re-parse from disk\n}","preventionTips":["Always parse the .sy content with lute before normalizing.","Check parse errors from the previous step; do not propagate nil trees.","Treat a nil Root as a parse failure signal, not a normalization issue."],"tags":["validation","null","document-tree"],"backgroundTag":"null-argument","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}