siyuan-note/siyuan · error
cannot generate notebook crypto backup without KEK
Error message
cannot generate notebook crypto backup without KEK
What it means
saveNotebookCryptoBackup nil-guard: it was invoked with a nil KEK. A backup written without a KEK has an empty KEKMAC and would be rejected by deriveKEK/recovery paths — creating an unrecoverable state — so generation is refused outright (design §19).
Source
Thrown at kernel/model/crypto.go:382
if err := writeNotebookCryptoBackupData(nc, kek); err != nil {
return fmt.Errorf("failed to persist key backup: %w", err)
}
Conf.m.Lock()
*Conf.NotebookCrypto = *nc
Conf.m.Unlock()
Conf.Save()
IncSync()
return nil
}
// saveNotebookCryptoBackup 把当前 NotebookCrypto(含 MasterSalt/KEKVerifier/KDFParams)备份到 DataDir。
// kek 必须非 nil:在 Checksum 定型后计算 KEKMAC 并落盘,保证恢复路径可通过 MAC 校验。
// 无 KEK 生成的备份 KEKMAC 必为空,会被 deriveKEK/恢复路径拒绝,等于制造无法解锁的状态(详见设计 §19)。
func saveNotebookCryptoBackup(kek []byte) error {
if kek == nil {
// 无 KEK 时不得生成当前格式备份:KEKMAC 缺失会被 deriveKEK/恢复路径拒绝,
// 生成即等于制造无法解锁的状态。
return errors.New("cannot generate notebook crypto backup without KEK")
}
Conf.m.Lock()
nc := *Conf.NotebookCrypto // 值拷贝
prepareBackupForWrite(&nc)
nc.KEKMAC = computeKEKMAC(&nc, kek)
if !notebookCryptoConfigurationComplete(&nc) {
Conf.m.Unlock()
return errors.New("cannot save incomplete notebook crypto configuration")
}
Conf.NotebookCrypto.Spec = nc.Spec
Conf.NotebookCrypto.BackupID = nc.BackupID
Conf.NotebookCrypto.CreatedAt = nc.CreatedAt
Conf.NotebookCrypto.Checksum = nc.Checksum
Conf.NotebookCrypto.KEKMAC = nc.KEKMAC // 保持 Conf 与备份文件的 KEKMAC 一致
Conf.m.Unlock()
backupPath := dataCryptoBackupPath()
if err := os.MkdirAll(filepath.Dir(backupPath), 0755); err != nil {
return fmt.Errorf("mkdir notebook crypto backup dir failed: %w", err)View on GitHub (pinned to 8641553a1f)
Solutions
- Ensure the KEK is derived (password change/enable completed) before saving the backup
- Retry the enabling/password-change operation that supplies the KEK
- Never bypass the guard by writing a MAC-less backup
Defensive patterns
Strategy: type-guard
When it happens
Trigger: Thrown at kernel/model/crypto.go:382 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/614d25ad1cd5c6d1.
Report an issue: GitHub.