{"record":{"id":"c4d6c8d9bb643c1c","repo":"siyuan-note/siyuan","slug":"query-database-bound-blocks-in-notebook-s-faile","errorCode":null,"errorMessage":"query database-bound blocks in notebook [%s] failed: %w","messagePattern":"query database-bound blocks in notebook \\[(.+?)\\] failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/mount.go","lineNumber":286,"sourceCode":"\tif !ast.IsNodeIDPattern(boxID) {\n\t\treturn errors.New(\"invalid notebook ID\")\n\t}\n\tif _, loaded := boxLock.LoadOrStore(boxID, true); loaded {\n\t\terr = errors.New(Conf.language(239))\n\t\treturn\n\t}\n\tdefer boxLock.Delete(boxID)\n\n\tif util.IsReservedFilename(boxID) {\n\t\treturn fmt.Errorf(\"can not remove [%s] caused by it is a reserved file\", boxID)\n\t}\n\n\tFlushTxQueue()\n\tsql.FlushQueue()\n\t// 索引和笔记本目录删除后无法再读取 custom-avs，需提前收集；实际删除成功后再清理绑定行。\n\tdeletedAttrViewBlockIDs, err := collectBoxDeletedAttributeViewBlocks(boxID)\n\tif nil != err {\n\t\treturn fmt.Errorf(\"query database-bound blocks in notebook [%s] failed: %w\", boxID, err)\n\t}\n\tisUserGuide := IsUserGuide(boxID)\n\tlocalPath := filepath.Join(util.DataDir, boxID)\n\tif !filelock.IsExist(localPath) {\n\t\tremoveHPathRefreshBox(boxID)\n\t\tforgetRuntimeNormalBox(boxID)\n\t\tremoveMasterPasswordMigrationBox(boxID)\n\t\treturn\n\t}\n\tif !gulu.File.IsDir(localPath) {\n\t\treturn fmt.Errorf(\"can not remove [%s] caused by it is not a dir\", boxID)\n\t}\n\n\t// 删目录前固定加密状态，确保后续历史、资源和索引清理始终使用同一个安全边界。\n\tisEncrypted := IsEncryptedBox(boxID)\n\tif !isUserGuide {\n\t\tif err = EnsureAssetPrefixLocal(localPath); err != nil {\n\t\t\treturn","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/mount.go#L268-L304","documentation":"Before deleting the notebook directory, RemoveBox calls collectBoxDeletedAttributeViewBlocks, which queries the SQLite index for database (attribute-view) blocks bound to the notebook so bound rows can be cleaned up after deletion. If that query fails, removal aborts with \"query database-bound blocks in notebook [%s] failed: %w\" wrapping the underlying SQL error. The notebook is left intact because the query must succeed before the directory is removed.","triggerScenarios":"sql.QueryBoundBlockAVIDsInBox failing while collecting custom-av bindings — usually when siyuan.db is corrupted, locked by another writer, or the index queue is in a bad state; it can also surface after a crashed index transaction left the blocks tables unreadable for that box.","commonSituations":"SQLite database corruption after a hard power-off or disk-full during indexing; database file locked by a second SiYuan instance pointed at the same workspace; version-upgrade migrations partially applied; antivirus locking siyuan.db on Windows.","solutions":["Inspect the wrapped (%w) inner error in logs to identify the SQL failure; fix that root cause first","Ensure no second kernel instance is using the same workspace (siyuan.db file lock)","If the database is corrupted, close the kernel and run SQLite integrity/recovery (PRAGMA integrity_check; .recover) on data/index/siyuan.db, then rebuild the index (Ctrl+F5 / 'Rebuild Index')","After the DB is healthy, retry the notebook removal — the pre-delete collection is re-run on each attempt"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check DB readability before attempting removal\nrows, err := query(\"SELECT count(*) FROM blocks WHERE box = ?\", boxID)\nif err != nil { return fmt.Errorf(\"index db unreadable for %s: %w\", boxID, err) }","typeGuard":null,"tryCatchPattern":"if err := removeNotebook(boxID); err != nil {\n    var qe *fmt.WrapError // unwrap the %w chain\n    if strings.HasPrefix(err.Error(), \"query database-bound blocks\") {\n        // do NOT retry blindly: repair/rebuild siyuan.db first, then retry\n        rebuildIndex()\n        return removeNotebook(boxID)\n    }\n    return err\n}","preventionTips":["Avoid running multiple kernel instances on the same workspace","Run on a filesystem/journal setup that survives power loss, and back up data/index/siyuan.db","Rebuild the index after any abnormal kernel termination before doing destructive notebook operations","Monitor disk-full conditions: failed index transactions are a common root cause"],"tags":["database","sqlite","notebook","precondition-failed"],"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"}