siyuan-note/siyuan · error

Conf.Language(312)

Error message

Conf.Language(312)

What it means

EnableEncryptedNotebook rejects the call when the feature is already enabled and fully configured (Conf.NotebookCrypto.Enabled plus notebookCryptoConfigurationComplete). The localized message Conf.Language(312) is 'Encrypted notebook feature is already enabled'. Re-enabling would overwrite the existing MasterSalt/KEK parameters, so the guard protects existing encrypted notebooks.

Source

Thrown at kernel/model/crypto.go:1008

	return EnableEncryptedNotebook(password)
}

// EnableEncryptedNotebook 启用加密笔记本功能:生成 MasterSalt、派生 KEK、写入校验值并持久化。
// 重复调用(已启用)返回错误,避免覆盖现有加密笔记本的密钥参数。
// 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 {

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Check Conf.NotebookCrypto.Enabled (or the API/config state) before calling EnableEncryptedNotebook and skip if already enabled
  2. Treat this message as success/idempotent no-op in automation instead of retrying
  3. If the intent is to change keys, disable the feature first (after removing encrypted notebooks) then re-enable

Example fix

// before
EnableEncryptedNotebook(password)
// after
if !Conf.NotebookCrypto.Enabled { EnableEncryptedNotebook(password) }
Defensive patterns

Strategy: validation

Validate before calling

if Conf.NotebookCrypto.Enabled && Conf.NotebookCrypto.MasterSalt != "" {
	// already enabled; skip
	return nil
}
return EnableEncryptedNotebook(password)

Try / catch

if err := EnableEncryptedNotebook(pw); err != nil && err.Error() == Conf.Language(312) {
	// idempotent no-op
	return nil
}

Prevention

When it happens

Trigger: Calling EnableEncryptedNotebook a second time after a successful first enable; the frontend settings toggle invoking enable while the feature flag is already on and complete in conf.json.

Common situations: Double-invocation from a UI retry loop or duplicate request; a script that enables the feature idempotently; state restored from an existing workspace conf where the feature was already turned on.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/00eebf53d20ab848. Report an issue: GitHub.