{"record":{"id":"275c49555050728d","repo":"siyuan-note/siyuan","slug":"tree-not-found","errorCode":null,"errorMessage":"tree not found","messagePattern":"tree not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/tree.go","lineNumber":205,"sourceCode":"\t\tif data, err = DecryptFile(boxID, relPath, dek, data); err != nil {\n\t\t\tlogging.LogErrorf(\"decrypt tree [path=%s] failed: %s\", localPath, err)\n\t\t\treturn\n\t\t}\n\t}\n\n\tret, err = dataparser.ParseJSONWithoutFix(data, luteEngine.ParseOptions)\n\tif err != nil {\n\t\tlogging.LogErrorf(\"parse json to tree [%s] failed: %s\", localPath, err)\n\t\treturn\n\t}\n\treturn\n}\n\nvar (\n\tErrBoxNotFound   = errors.New(\"notebook not found\")\n\tErrBoxClosed     = errors.New(\"notebook closed\")\n\tErrBlockNotFound = errors.New(\"block not found\")\n\tErrTreeNotFound  = errors.New(\"tree not found\")\n\tErrIndexing      = errors.New(\"indexing\")\n\tErrBoxUnindexed  = errors.New(\"notebook unindexed\")\n\tErrInvalidID     = errors.New(\"invalid id\")\n)\n\nfunc LoadTreeByBlockIDWithReindex(id string) (ret *parse.Tree, err error) {\n\treturn LoadTreeByBlockIDWithReindexInBox(id, \"\")\n}\n\n// LoadTreeByBlockIDWithReindexInBox 与 LoadTreeByBlockIDWithReindex 一致，但按 boxID 路由 blocktree 查询。\nfunc LoadTreeByBlockIDWithReindexInBox(id, boxID string) (ret *parse.Tree, err error) {\n\tif \"\" == id {\n\t\tlogging.LogWarnf(\"block id is empty\")\n\t\treturn nil, ErrTreeNotFound\n\t}\n\n\tbt := treenode.GetBlockTreeInBox(id, boxID)\n\tif nil == bt && \"\" == boxID {","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/tree.go#L187-L223","documentation":"Sentinel error model.ErrTreeNotFound (kernel/model/tree.go:205). Returned when the document tree for an ID cannot be located or loaded: an empty id (loadTreeByBlockIDWithReindexInBox logs 'block id is empty' and returns it), an ID failing ast.IsNodeIDPattern, or no blocktree entry even after the kernel's fallback attempt to index the tree from the filesystem (indexTreeInFilesystem).","triggerScenarios":"Passing an empty id string; passing a malformed id that does not match the SiYuan node-ID pattern; an id whose .sy file or blocktree entry is gone (manually deleted files, corrupted blocktree.db) so even the reindex fallback cannot find it. Distinguish from ErrIndexing: if a kernel-wide index task is running, that sentinel is returned instead.","commonSituations":"Callers forwarding unvalidated query params; ids truncated in copy-paste; hand-edited or externally-deleted notebook contents desyncing blocktree.db from disk.","solutions":["Pass a real SiYuan block/document id (the 14-digit timestamp + dash + 7-char suffix form issued by the kernel)","If indexing is in progress, wait and retry; ErrIndexing signals that case","If the id should exist, rebuild the index (设置 - 搜索 - 重建索引) to re-derive blocktree from the .sy files on disk"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate shape and existence up front:\nif !ast.IsNodeIDPattern(id) || id == \"\" {\n\t// reject before calling the kernel\n}\n// POST /api/query/block {\"id\": id} to confirm it resolves","typeGuard":"func isTreeNotFound(err error) bool {\n\treturn errors.Is(err, model.ErrTreeNotFound)\n}","tryCatchPattern":"if tree, err := model.LoadTreeByBlockID(id); err != nil {\n\tif errors.Is(err, model.ErrTreeNotFound) {\n\t\t// empty/malformed id, or doc truly gone - do not blindly retry\n\t} else if errors.Is(err, model.ErrIndexing) {\n\t\t// retry after indexing completes\n\t}\n}","preventionTips":["Always propagate kernel-issued ids end-to-end; never synthesize them","Check for empty id before calling load APIs","Keep ErrIndexing and ErrTreeNotFound handling distinct: one is transient, the other is not"],"tags":["block","tree","sentinel-error","not-found","indexing"],"backgroundTag":"tree-load-failed","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}