siyuan-note/siyuan · error
check encrypted notebook history failed
Error message
check encrypted notebook history failed: %w
What it means
During pre-enable checks, EnableEncryptedNotebook calls scanEncryptedNotebookHistory() to detect deleted-notebook history that indicates a prior key domain; if that scan errors the function returns fmt.Errorf("check encrypted notebook history failed: %w", historyErr). Skipping the check could let a new MasterSalt overwrite a key domain still recoverable from history or the global backup.
Solutions
- Inspect the wrapped cause (%w) for the underlying history-scan error and repair it (restore history.db from backup, fix permissions, free disk space)
- Check the integrity of history.db (SQLite integrity check) and rebuild history indexes if corrupt
- Retry after the environment is fixed; the scan is read-only
- If a prior key domain is later detected, use the recovery-from-backup path instead of generating fresh key material
Defensive patterns
Strategy: try-catch
Try / catch
if err := model.EnableEncryptedNotebook(password); err != nil {
if strings.Contains(err.Error(), "check encrypted notebook history failed") {
// inspect errors.Unwrap(err) for the history.db cause
}
return err
} Prevention
- Keep history.db healthy: avoid killing the kernel mid-history-write and run integrity checks after crashes
- Ensure read permissions on the workspace history storage path
- Back up history.db and data/ crypto backup before enabling encryption
- After an interrupted sync/restore, verify history integrity before re-attempting enable
When it happens
Trigger: scanEncryptedNotebookHistory fails while EnableEncryptedNotebook (or EnableEncryptedNotebookWithSync) runs — usually history.db is unreadable/corrupt, the history directory has bad permissions, or an I/O error occurs during the scan.
Common situations: Corrupted or locked history.db in the workspace; partial restore or interrupted sync leaving history in a bad state; running without read permission on the history storage path; tests with a broken/missing history fixture.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- list encrypted notebooks failed
- 345
- access to sensitive workspace file is forbidden
- accessing assets in encrypted notebook
- ambiguous asset path
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/c720a3e19693819e.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/crypto.go:1017
}
notebookCryptoMu.Lock()
defer notebookCryptoMu.Unlock()
Conf.m.RLock()
current := *Conf.NotebookCrypto
Conf.m.RUnlock()
if current.Enabled && notebookCryptoConfigurationComplete(¤t) {
return errors.New(Conf.Language(312))
}
hasEncrypted, listErr := hasEncryptedNotebook()
if listErr != nil {
return fmt.Errorf("list encrypted notebooks failed: %w", listErr)
}
hasHistory, historyErr := scanEncryptedNotebookHistory()
if historyErr != nil {
return fmt.Errorf("check encrypted notebook history failed: %w", historyErr)
}
hasBackup := filelock.IsExist(dataCryptoBackupPath())
if hasEncrypted || hasHistory || hasBackup {
// 现存笔记本、已删除笔记本历史或全局备份均表示已有密钥域,必须恢复并认证,不能生成新 MasterSalt。
kek, restoreErr := tryRestoreNotebookCryptoFromBackupLocked(password)
if kek != nil {
zeroAndClear(kek)
}
if restoreErr != nil {
if strings.Contains(restoreErr.Error(), Conf.Language(311)) {
return errors.New(Conf.Language(311))
}
return errors.New(Conf.Language(315))
}
logging.LogInfof("encrypted notebook re-enabled with authenticated recovery key material")
return nil
}
View on GitHub (pinned to 9f775e8a12)