siyuan-note/siyuan · error
tree is empty
Error message
tree is empty
What it means
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.
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.
Example fix
// before
NormalizeTreeForRead(tree)
// after
if tree == nil || tree.Root == nil {
return errors.New("tree was not parsed")
}
NormalizeTreeForRead(tree) Defensive patterns
Strategy: type-guard
Validate before calling
if (tree == null || tree.Root == null) { /* parse first or abort */ } Type guard
func hasRoot(t *parse.Tree) bool { return t != nil && t.Root != nil } Try / catch
if err := filesys.NormalizeTreeForRead(tree); err != nil {
// tree empty or spec check failed; re-parse from disk
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- attribute view custom color must not be null
- Conf.Language(87)
- configuration must not be null
- Field [ ] must not be null
- invalid block structure: block node is nil
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/6b7c3f1b085d861d.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/filesys/tree.go:229
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
}
if err = treenode.RefreshTableCellRichProjection(tree.Root); 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
}View on GitHub (pinned to 9f775e8a12)