siyuan-note/siyuan · error
ErrTreeNotFound
ErrTreeNotFound
Error message
tree not found
What it means
ErrTreeNotFound is the sentinel error meaning the document tree for a given ID could not be loaded. Doc-info and path-lookup functions (getDocInfo, getBlockInfo, getHPathByID, getFullHPathByID, export prep) return it when no tree matches the ID. API handlers deliberately swallow it in some endpoints because 'not found' should degrade quietly rather than surface as a message.
Source
Thrown at kernel/model/tree.go:213
}
}
if err = treenode.CheckSpecJSON(data); nil != err {
return
}
ret, err = dataparser.ParseJSONWithoutFix(data, luteEngine.ParseOptions)
if err != nil {
logging.LogErrorf("parse json to tree [%s] failed: %s", localPath, err)
return
}
return
}
var (
ErrBoxNotFound = errors.New("notebook not found")
ErrBoxClosed = errors.New("notebook closed")
ErrBlockNotFound = errors.New("block not found")
ErrTreeNotFound = errors.New("tree not found")
ErrIndexing = errors.New("indexing")
ErrBoxUnindexed = errors.New("notebook unindexed")
ErrInvalidID = errors.New("invalid id")
)
func LoadTreeByBlockIDWithReindex(id string) (ret *parse.Tree, err error) {
return LoadTreeByBlockIDWithReindexInBox(id, "")
}
// LoadTreeByBlockIDWithReindexInBox 与 LoadTreeByBlockIDWithReindex 一致,但按 boxID 路由 blocktree 查询。
func LoadTreeByBlockIDWithReindexInBox(id, boxID string) (ret *parse.Tree, err error) {
if "" == id {
logging.LogWarnf("block id is empty")
return nil, ErrTreeNotFound
}
bt := treenode.GetBlockTreeInBox(id, boxID)
if nil == bt && "" == boxID {View on GitHub (pinned to 8641553a1f)
Solutions
- Confirm the document still exists (/api/filetree/getHPathByID) and update or remove stale references to the deleted doc
- Rebuild the notebook index if the .sy file exists but the in-memory/blocktree index lost it
- Handle errors.Is(err, model.ErrTreeNotFound) as an expected 'missing' case in API callers (as block.go:710 does) instead of reporting an error message
Example fix
// before
ret.Msg = err.Error()
// after
if err != nil && !errors.Is(err, model.ErrTreeNotFound) {
ret.Msg = err.Error()
} Defensive patterns
Strategy: try-catch
Validate before calling
hp, err := getHPathByID(id)
if err != nil || hp == "" { return fmt.Errorf("doc %s not found", id) } Try / catch
if errors.Is(err, model.ErrTreeNotFound) {
// treat as expected missing-doc case; degrade quietly
return nil
} Prevention
- Confirm documents exist after sync before referencing their IDs
- Rebuild the index if lookups fail for docs that exist on disk
- Treat missing trees as a normal outcome in plugins, not a crash
When it happens
Trigger: getDocInfo/getBlockInfo called with an ID absent from the index; getHPathByID/getPathByID/getFullHPathByID with a deleted doc's ID; prepareExportAssets encountering a missing tree during export.
Common situations: Client or plugin requesting a document deleted on another device before sync removed it locally; corrupted blocktree index missing the tree; links/bookmarks pointing at removed documents.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4562081f91cefdb5.
Report an issue: GitHub.