siyuan-note/siyuan · error

list encrypted notebooks failed: %w

Error message

list encrypted notebooks failed: %w

What it means

EnableEncryptedNotebook returns a wrapped error at line 991 when hasEncryptedNotebook() fails. This is a precondition scan used to decide whether to recover an existing key domain or generate a fresh MasterSalt; if the scan itself errors, the function cannot safely proceed in either direction and aborts. The underlying error is preserved via %w.

Source

Thrown at kernel/model/crypto.go:991

// KEK 不缓存——启用后用户需对每个加密笔记本单独调 UnlockBox 解锁。
func EnableEncryptedNotebook(password string) error {
	if len(password) == 0 {
		return errors.New("password must not be empty")
	}

	notebookCryptoMu.Lock()
	defer notebookCryptoMu.Unlock()

	Conf.m.RLock()
	current := *Conf.NotebookCrypto
	Conf.m.RUnlock()
	if current.Enabled && notebookCryptoConfigurationComplete(&current) {
		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))
		}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Inspect the wrapped error (errors.Unwrap) to identify whether it is blocktree, filesystem, or notebook-metadata related.
  2. Resolve the underlying storage/index issue (repair permissions, close competing locks, reindex) and retry.
  3. Do not attempt to bypass the scan by clearing state — that risks generating a new key domain over existing encrypted data.
Defensive patterns

Strategy: try-catch

Try / catch

// Unwrap and route the precondition failure.
if err := model.EnableEncryptedNotebook(password); err != nil {
    var unwrapped error
    if errors.As(err, &unwrapped) {
        log.Printf("notebook scan failed: %v", unwrapped)
    }
}

Prevention

When it happens

Trigger: hasEncryptedNotebook() returns a non-nil error while listing/scanning notebooks for encryption markers. Causes: notebook index/blocktree read failure, filesystem error reading notebook metadata, or a corrupted notebook directory.

Common situations: Workspace with a corrupted .sy metadata file; blocktree.db locked or unreadable; notebook directory permission error; concurrent unmount/mount racing with the scan; storage media degradation.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/c71c2730a2248bcd. Report an issue: GitHub.