{"record":{"id":"11d788467cb2e1da","repo":"siyuan-note/siyuan","slug":"encrypted-blocktree-db-not-opened-for-box","errorCode":null,"errorMessage":"encrypted blocktree db not opened for box ","messagePattern":"encrypted blocktree db not opened for box ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/treenode/blocktree.go","lineNumber":1064,"sourceCode":"\t}\n\tif err = ensureHPathIndexes(boxDB); err != nil {\n\t\treturn\n\t}\n\tif err = cleanupInvalidBlockTrees(boxDB); err != nil {\n\t\treturn\n\t}\n\treturn\n}\n\n// --- box-scoped wrapper（加密笔记本用独立 db，否则用全局 db）---\n// 加密笔记本未解锁（db 未打开）时 fail-closed：绝不回退全局库，避免加密笔记本块树操作污染全局 blocktree.db。\n\nfunc queryForBox(box, stmt string, args ...any) (*sql.Rows, error) {\n\tif boxDB := getEncryptedBlockTreeDB(box); boxDB != nil {\n\t\treturn boxDB.Query(stmt, args...)\n\t}\n\tif IsEncryptedBoxFn != nil && IsEncryptedBoxFn(box) {\n\t\treturn nil, errors.New(\"encrypted blocktree db not opened for box \" + box)\n\t}\n\treturn query(stmt, args...)\n}\n\nfunc queryRowForBox(box, stmt string, args ...any) *sql.Row {\n\tif boxDB := getEncryptedBlockTreeDB(box); boxDB != nil {\n\t\treturn boxDB.QueryRow(stmt, args...)\n\t}\n\tif IsEncryptedBoxFn != nil && IsEncryptedBoxFn(box) {\n\t\treturn nil\n\t}\n\treturn queryRow(stmt, args...)\n}\n\nfunc execForBox(box, stmt string, args ...any) (sql.Result, error) {\n\tif boxDB := getEncryptedBlockTreeDB(box); boxDB != nil {\n\t\treturn boxDB.Exec(stmt, args...)\n\t}","sourceCodeStart":1046,"sourceCodeEnd":1082,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/treenode/blocktree.go#L1046-L1082","documentation":"queryForBox routes block-tree SQL queries to a per-box encrypted database when one is open. If the box is marked encrypted (IsEncryptedBoxFn) but its encrypted blocktree DB was never opened/attached, the query cannot safely fall back to the plaintext DB (that would bypass authentication), so it fails with this error naming the box.","triggerScenarios":"Calling GetBlockTreesByBoxID, GetRootBlockIDsByBoxID, GetBlockTreeRootsByHPath, GetBlockTreesByTypeInBox, GetBlockTreesByPathPrefix, or RemoveBlockTreesByBoxID for an encrypted box whose encrypted blocktree DB handle is not registered via getEncryptedBlockTreeDB.","commonSituations":"Querying an encrypted notebook before its lease/key was unlocked (e.g. at boot, before opening the box), or after the encrypted DB was closed; calling kernel APIs directly for an encrypted box without going through the unlock flow.","solutions":["Open/unlock the encrypted notebook first so its encrypted blocktree DB is attached, then retry the query.","Check the box ID spelling/validity; an incorrect box ID can be wrongly classified as encrypted.","If running embeded code, ensure IsEncryptedBoxFn state matches actual opened DBs — re-open the box DB instead of querying."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"rows, err := queryForBox(box, stmt, args...)\nif err != nil && strings.HasPrefix(err.Error(), \"encrypted blocktree db not opened\") {\n    // unlock/open the encrypted box DB, then retry once\n}","preventionTips":["Always open/unlock encrypted notebooks before issuing per-box block-tree queries.","Sequence queries after the box-open step in startup code.","Validate box IDs before querying."],"tags":["database","encryption","blocktree"],"backgroundTag":"database-query-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"}