siyuan-note/siyuan · error

Encrypted notebook feature is not enabled

Error message

Encrypted notebook feature is not enabled

What it means

Error "Encrypted notebook feature is not enabled" thrown in siyuan-note/siyuan.

Solutions

  1. Check whether encrypted notebooks are enabled before calling this operation; the key backup can only be restored or used when the feature is active.
  2. If the feature was disabled, re-enable it first via Settings, then retry the operation.
  3. Guard the calling code with the enabled flag so this path is unreachable when the feature is off.

When it happens

Trigger: Thrown at kernel/model/crypto.go:1173 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/0b554239370af0bc. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/crypto.go:1173

	*Conf.NotebookCrypto = *backup
	Conf.m.Unlock()
	Conf.Save()
	// 恢复成功后同步重写备份,确保配置和备份内容一致。
	// 调用方已持有 notebookCryptoMu,且 writeNotebookCryptoBackupData 不再申请该锁,故无死锁;
	// 同步写避免与 ChangeMasterPassword 的并发备份写竞争同一文件(lost update 导致 verifier 被回退)。
	nc := *backup
	if err := writeNotebookCryptoBackupData(&nc, kek); err != nil {
		logging.LogWarnf("rewrite notebook crypto backup after restore failed: %s", err)
	}
	logging.LogInfof("notebook crypto restored from backup (e.g. after sync to a new device)")
	return kek, nil
}

// deriveNotebookCryptoBackupCandidate 对同步备份做无副作用验证,并确认它覆盖全部现有加密笔记本。
func deriveNotebookCryptoBackupCandidate(password string) (backup *conf.NotebookCrypto, kek []byte, err error) {
	backup, err = loadNotebookCryptoBackup()
	if err != nil || backup == nil || len(backup.MasterSalt) == 0 || len(backup.KEKVerifier) == 0 {
		return nil, nil, errors.New(Conf.Language(310))
	}
	params, validErr := util.ValidateArgon2Params(backup.KDFParams)
	if validErr != nil {
		return nil, nil, errors.New(Conf.Language(317))
	}
	kek = util.DeriveKey(password, backup.MasterSalt, params)
	decrypted, decryptErr := util.DecryptWithAAD(kek, backup.KEKVerifier, []byte("siyuan:kek-verifier"))
	if decryptErr != nil || string(decrypted) != string(kekVerifierMagic) {
		zeroAndClear(kek)
		return nil, nil, errors.New(Conf.Language(311))
	}
	if backup.Spec != conf.CurrentNotebookCryptoSpec || backup.Checksum == "" ||
		len(backup.KEKMAC) == 0 || !verifyKEKMAC(backup, kek) {
		zeroAndClear(kek)
		return nil, nil, errors.New(Conf.Language(316))
	}
	if !verifyKEKAgainstExistingBoxes(kek) || !verifyKEKAgainstEncryptedHistory(kek) {
		zeroAndClear(kek)

View on GitHub (pinned to afa823b6b4)