siyuan-note/siyuan · error
tree is empty
Error message
tree is empty
What it means
Returned by `filesys.NormalizeTreeForRead` when the tree or its `Root` is nil. The function applies read-only normalization (spec check, spec upgrade, attribute escaping) and cannot proceed on an empty tree, so it fails fast rather than nil-dereferencing.
Source
Thrown at kernel/filesys/tree.go:225
return
}
ret, err = LoadTreeByData(data, boxID, p, luteEngine)
if nil == err {
cache.SetTreeDataInBox(rootID, boxID, data)
}
return
}
func LoadTree(boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err error) {
ret, _, err = LoadTreeWithFix(boxID, p, luteEngine)
return
}
// NormalizeTreeForRead 对只读树应用与文件加载一致的规范化处理,但不写回磁盘。
func NormalizeTreeForRead(tree *parse.Tree) (err error) {
if nil == tree || nil == tree.Root {
return errors.New("tree is empty")
}
if err = treenode.CheckSpec(tree); nil != err {
return
}
treenode.UpgradeSpec(tree)
escapeAttributeValues(tree)
return
}
func LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err error) {
ret, err = parseJSON2Tree(boxID, p, data, luteEngine)
if nil != err {
logging.LogErrorf("parse tree [%s] failed: %s", p, err)
return
}
ret.Path = p
ret.Root.Path = p
View on GitHub (pinned to 251596fc0d)
Solutions
- Check the tree and error from `LoadTree`/`LoadTreeByData` before passing the tree to `NormalizeTreeForRead`.
- If constructing trees in code, always set `tree.Root` before normalizing.
- Log and propagate the error so callers do not silently continue with no tree.
Example fix
// before
tree, _ := filesys.LoadTree(box, p, lute)
filesys.NormalizeTreeForRead(tree) // panics on nil
// after
tree, err := filesys.LoadTree(box, p, lute)
if err != nil || tree == nil {
return err
}
if err := filesys.NormalizeTreeForRead(tree); err != nil {
return err
} Defensive patterns
Strategy: type-guard
Validate before calling
// Guard the tree before normalizing:
if tree == nil || tree.Root == nil {
return errors.New("tree is empty")
} Type guard
func isNonEmptyTree(t *parse.Tree) bool {
return t != nil && t.Root != nil
} Prevention
- Always check both the tree pointer and the error from Load functions.
- When constructing trees in code, set Root immediately after allocation.
- Return early on upstream errors so callers never reach normalize with nil.
When it happens
Trigger: Calling `NormalizeTreeForRead` on a tree that failed to load (nil return) or on a freshly-allocated `parse.Tree` whose `Root` was never set. The check `nil == tree || nil == tree.Root` covers both.
Common situations: Chaining a load that returned a nil tree without checking the error; constructing a tree manually for testing and forgetting `Root`; a corrupted file that parsed to an empty tree.
Related errors
- invalid path
- tree not found
- invalid block structure: %s [%s] cannot contain %s [%s]
- Failed to update agent session permission
- Agent capability name and description are required
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/6b7c3f1b085d861d.
Report an issue: GitHub.