{"record":{"id":"bb2039088ea7b8fc","repo":"siyuan-note/siyuan","slug":"cannot-rebuild-encrypted-indexes-w","errorCode":null,"errorMessage":"cannot rebuild encrypted indexes: %w","messagePattern":"cannot rebuild encrypted indexes: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"kernel/model/encrypted_index.go","lineNumber":35,"sourceCode":"\t\"github.com/siyuan-note/siyuan/kernel/util\"\n)\n\n// openEncryptedBoxIndexes 只在源文档认证成功后重建不兼容或损坏的派生索引，保留源密文和密钥材料。\n// 调用方持有笔记本写锁，且已验证密钥包络和笔记本元数据。\nfunc openEncryptedBoxIndexes(boxID string, dek []byte) error {\n\topen := func() error {\n\t\tif err := sql.OpenEncryptedDB(boxID, dek); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn treenode.OpenEncryptedBlockTreeDB(boxID, dek)\n\t}\n\tif err := open(); err == nil {\n\t\treturn nil\n\t}\n\tsql.CloseEncryptedDB(boxID)\n\ttreenode.CloseEncryptedBlockTreeDB(boxID)\n\tif err := authenticateEncryptedIndexDocuments(boxID, dek); err != nil {\n\t\treturn fmt.Errorf(\"cannot rebuild encrypted indexes: %w\", err)\n\t}\n\tsql.RemoveEncryptedDBFile(boxID)\n\ttreenode.RemoveEncryptedBlockTreeDBFile(boxID)\n\tif err := open(); err != nil {\n\t\tsql.RemoveEncryptedDBFile(boxID)\n\t\ttreenode.RemoveEncryptedBlockTreeDBFile(boxID)\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc authenticateEncryptedIndexDocuments(boxID string, dek []byte) error {\n\tboxDir := filepath.Join(util.DataDir, boxID)\n\tids := map[string]struct{}{}\n\treturn filepath.WalkDir(boxDir, func(filePath string, entry fs.DirEntry, walkErr error) error {\n\t\tif walkErr != nil {\n\t\t\treturn walkErr\n\t\t}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/encrypted_index.go#L17-L53","documentation":"When the encrypted SQLite/blocktree index files for a box fail to open, openEncryptedBoxIndexes falls back to rebuilding them: it closes the DBs, re-authenticates every encrypted document with the box DEK, then recreates the index files. If authenticateEncryptedIndexDocuments fails, the rebuild is aborted and wrapped with \"cannot rebuild encrypted indexes: %w\". The underlying error usually indicates a document that cannot be decrypted or parsed with the given DEK.","triggerScenarios":"Opening a box whose siyuan.db or blocktree.db is missing/corrupt triggers the rebuild path; during the rebuild, authenticateEncryptedIndexDocuments hits a .sy file whose decryption (wrong DEK), authentication (tampered ciphertext/AAD), or parsing fails.","commonSituations":"Index files deleted or corrupted by a crash or manual cleanup while documents remain; DEK/key-envelope mismatch after a failed or partial key migration; manually copied .sy files from another workspace or a different key generation into the box data directory.","solutions":["Read the wrapped %w cause: if it is an authentication/decrypt failure, the document ciphertext does not match the current DEK — restore the document from backup/sync history.","Verify the box was unlocked with the correct passphrase and that no key-envelope migration is pending or half-applied.","Remove or quarantine the offending .sy file and retry the open so the rebuild can complete, then restore that document from sync.","If the cause is a parse error, check whether the .sy file is truncated and re-fetch it from the sync repo."],"exampleFix":"// before\nerr := model.OpenBox(boxID) // \"cannot rebuild encrypted indexes: authenticate ... failed\"\n// after\nif err := model.UnlockBox(boxID, passphrase); err != nil { return err }\nif err := model.OpenBox(boxID); err != nil {\n    log.Logf(\"rebuild failed: %v; restoring doc from sync\", err)\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := model.OpenBox(boxID); err != nil {\n    var rebuildErr *fmt.WrapError // inspect wrapped cause\n    log.Logf(\"encrypted index rebuild failed: %v\", err)\n    // if cause is decrypt/auth failure: restore doc from sync, then retry\n}","preventionTips":["Never hand-edit or delete .sy files inside encrypted boxes","Complete key-envelope migrations fully before reopening boxes","Keep a valid sync/backup snapshot before index maintenance","Surface wrapped %w causes in logs to identify the offending document"],"tags":["encryption","index","rebuild","integrity"],"backgroundTag":"checksum-mismatch","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}