{"record":{"id":"fb48dc705a1ab597","repo":"siyuan-note/siyuan","slug":"block-tree-database-is-unavailable","errorCode":null,"errorMessage":"block tree database is unavailable","messagePattern":"block tree database is unavailable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/treenode/blocktree.go","lineNumber":52,"sourceCode":"\t\"github.com/88250/lute/parse\"\n\t\"github.com/siyuan-note/logging\"\n\t\"github.com/siyuan-note/siyuan/kernel/util\"\n)\n\ntype BlockTree struct {\n\tID       string // 块 ID\n\tRootID   string // 根 ID\n\tParentID string // 父 ID\n\tBoxID    string // 笔记本 ID\n\tPath     string // 文档数据路径\n\tHPath    string // 文档可读路径\n\tUpdated  string // 更新时间\n\tType     string // 类型\n}\n\nvar (\n\tdb                        *sql.DB\n\terrBlockTreeDBUnavailable = errors.New(\"block tree database is unavailable\")\n\n\tinitDatabaseLock = sync.RWMutex{}\n)\n\nfunc initDatabase(forceRebuild bool) {\n\tinitDatabaseLock.Lock()\n\tdefer initDatabaseLock.Unlock()\n\n\tinitDBConnection()\n\n\tif !forceRebuild {\n\t\tif !gulu.File.IsExist(util.BlockTreeDBPath) {\n\t\t\tforceRebuild = true\n\t\t}\n\t}\n\tif !forceRebuild {\n\t\t// 校验块树表是否可用，避免因上次重建被中断导致数据库文件存在但表缺失\n\t\tvar table string","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/treenode/blocktree.go#L34-L70","documentation":"errBlockTreeDBUnavailable signals that the block tree database (blocktree.db) has not been initialized or is not open, so tree lookup/count operations cannot run. Accessors such as CountTrees, CountBlocks, ExistBlockTree, GetBlockTree, scanQueryRow, and GetBlockTreeInExactBox return it instead of panicking; several count helpers deliberately swallow it and return zero (see blocktree.go:237/249). It is a sentinel error for 'the index DB is not ready'.","triggerScenarios":"Calling GetBlockTree/CountBlocks etc. before initDatabase has completed (e.g. very early during kernel boot) or after the blocktree DB failed to open; querying from a context where the workspace index was never built.","commonSituations":"Race during startup where plugins query block trees before initialization finishes; blocktree.db locked or corrupt so opening failed; calling index APIs from tests without initializing the DB.","solutions":["Ensure the kernel/workspace index is fully initialized before querying; wait for boot/index-ready signal","Trigger a tree index rebuild if blocktree.db is missing or corrupt","In callers, treat this sentinel like sql.ErrNoRows (return zero/default) when a default is acceptable, or retry after init"],"exampleFix":"// before\nbt := treenode.GetBlockTree(id) // nil + sentinel swallowed during boot\n// after\nif !indexReady() {\n    time.Sleep(500 * time.Millisecond) // or wait on init signal\n}\nbt := treenode.GetBlockTree(id)","handlingStrategy":"fallback","validationCode":"if (!kernelBooted()) await waitForKernelBoot();","typeGuard":null,"tryCatchPattern":"bt := treenode.GetBlockTree(id)\nif bt == nil {\n    // treat as 'not found / index not ready', retry after init or rebuild index\n}","preventionTips":["Do not query block-tree APIs before kernel initialization completes","Rebuild the index if blocktree.db is missing or corrupt","Treat zero results during boot as 'index warming', not a hard failure"],"tags":["database","blocktree","initialization"],"backgroundTag":"module-init-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}