{"record":{"id":"c720a3e19693819e","repo":"siyuan-note/siyuan","slug":"check-encrypted-notebook-history-failed-w","errorCode":null,"errorMessage":"check encrypted notebook history failed: %w","messagePattern":"check encrypted notebook history failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/crypto.go","lineNumber":995,"sourceCode":"\t}\n\n\tnotebookCryptoMu.Lock()\n\tdefer notebookCryptoMu.Unlock()\n\n\tConf.m.RLock()\n\tcurrent := *Conf.NotebookCrypto\n\tConf.m.RUnlock()\n\tif current.Enabled && notebookCryptoConfigurationComplete(&current) {\n\t\treturn errors.New(Conf.Language(312))\n\t}\n\n\thasEncrypted, listErr := hasEncryptedNotebook()\n\tif listErr != nil {\n\t\treturn fmt.Errorf(\"list encrypted notebooks failed: %w\", listErr)\n\t}\n\thasHistory, historyErr := scanEncryptedNotebookHistory()\n\tif historyErr != nil {\n\t\treturn fmt.Errorf(\"check encrypted notebook history failed: %w\", historyErr)\n\t}\n\thasBackup := filelock.IsExist(dataCryptoBackupPath())\n\tif hasEncrypted || hasHistory || hasBackup {\n\t\t// 现存笔记本、已删除笔记本历史或全局备份均表示已有密钥域，必须恢复并认证，不能生成新 MasterSalt。\n\t\tkek, restoreErr := tryRestoreNotebookCryptoFromBackupLocked(password)\n\t\tif kek != nil {\n\t\t\tzeroAndClear(kek)\n\t\t}\n\t\tif restoreErr != nil {\n\t\t\tif strings.Contains(restoreErr.Error(), Conf.Language(311)) {\n\t\t\t\treturn errors.New(Conf.Language(311))\n\t\t\t}\n\t\t\treturn errors.New(Conf.Language(315))\n\t\t}\n\t\tlogging.LogInfof(\"encrypted notebook re-enabled with authenticated recovery key material\")\n\t\treturn nil\n\t}\n","sourceCodeStart":977,"sourceCodeEnd":1013,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/crypto.go#L977-L1013","documentation":"EnableEncryptedNotebook returns a wrapped error at line 995 when scanEncryptedNotebookHistory() fails. This scan inspects deleted-notebook history for encrypted notebooks to ensure a new key domain is not created over history that would become unrecoverable. If the history scan errors, the function aborts (fail-closed) rather than risk orphaning historical WrappedDEKs.","triggerScenarios":"scanEncryptedNotebookHistory() returns a non-nil error while scanning deleted-notebook history records for encryption markers. Causes: history.db read failure, corrupted history index, or filesystem error traversing the history directory.","commonSituations":"history.db locked or corrupt; history directory permission error; large history triggering a timeout/OOM during scan; storage degradation affecting the history volume.","solutions":["Inspect the wrapped underlying error to localize the failure (history.db vs directory traversal).","Repair history storage (permissions, reindex history, free disk) and retry the enable.","Treat the failure as fail-closed — do not force-enable while history state is uncertain."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Unwrap the history-scan failure for targeted repair.\nif err := model.EnableEncryptedNotebook(password); err != nil {\n    if strings.Contains(err.Error(), \"encrypted notebook history\") {\n        // inspect/repair history.db and the history directory, then retry\n    }\n}","preventionTips":["Keep history.db and the history directory consistent and readable before enabling encryption.","Do not force-enable while history state is uncertain — the scan is fail-closed by design.","Free disk space and repair permissions if the history scan errors on I/O."],"tags":["crypto","encryption","history","filesystem","precondition"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}