{"record":{"id":"07e8c4938ec04ccd","repo":"siyuan-note/siyuan","slug":"block-not-found-07e8c4","errorCode":null,"errorMessage":"block not found","messagePattern":"block not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/tree.go","lineNumber":204,"sourceCode":"\t\trelPath := filepath.ToSlash(strings.TrimPrefix(localPath, filepath.Join(util.DataDir, boxID)+string(os.PathSeparator)))\n\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)","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/tree.go#L186-L222","documentation":"Sentinel error model.ErrBlockNotFound (kernel/model/tree.go:204), the most common not-found error in the kernel. It means a block ID has no entry in the blocktree (treenode.GetBlockTree returned nil) or a document path failed validation. Dozens of call sites return it (block.go, heading.go, listitem.go, search.go, export.go), and the transaction layer maps it to TxErrCodeBlockNotFound.","triggerScenarios":"Operations on a stale or deleted block ID (user removed the block after your code captured the id); calling block APIs while the database is still indexing; invalid document paths in file ops (tests in file_test.go show malformed parent paths also map to this sentinel).","commonSituations":"Plugins caching block IDs in long-lived state; API retries racing user deletions; fresh kernel boot before indexing commits; referencing blocks of an unindexed notebook.","solutions":["Verify the id exists first, e.g. POST /api/query/block {\"id\": \"<blockID>\"} or /api/block/getBlockInfo","If indexing may be in flight, wait for it to finish and retry once","If the id is persistently missing, rebuild the index (设置 - 搜索 - 重建索引) or verify the block was not deleted by the user","Match with errors.Is(err, model.ErrBlockNotFound); in transactions treat TxErr code TxErrCodeBlockNotFound as 'refresh your id cache'"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Confirm the block exists before operating on it:\n// POST /api/query/block {\"id\": \"<blockID>\"}\n// Empty result -> do not call block-mutating APIs; refresh your id source.","typeGuard":"func isBlockNotFound(err error) bool {\n\treturn errors.Is(err, model.ErrBlockNotFound)\n}","tryCatchPattern":"if err := model.SomeBlockOp(id); err != nil {\n\tswitch {\n\tcase errors.Is(err, model.ErrIndexing):\n\t\t// wait for indexing, retry once\n\tcase errors.Is(err, model.ErrBlockNotFound):\n\t\t// id is stale or deleted - drop it from caches, do not retry\n\tdefault:\n\t\t// propagate\n\t}\n}","preventionTips":["Validate block IDs with a blocks query before mutating operations","In transactions, handle TxErr code TxErrCodeBlockNotFound by refreshing cached ids","After user deletions or syncs, treat cached block IDs as suspect"],"tags":["block","sentinel-error","not-found","indexing","kernel-api"],"backgroundTag":"block-id-not-found","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}