siyuan-note/siyuan · error
no DEK cached for box " + boxID
Error message
no DEK cached for box " + boxID
What it means
GetDEK found no DEK cached for the given (valid, accessible) box ID. A DEK is only in cachedDEKs while the encrypted notebook is unlocked; for unencrypted boxes the DEK is populated when the notebook is loaded. Absence means the key was never loaded or was evicted/zeroed.
Solutions
- Ensure the notebook is loaded/unlocked (DEK populated) before calling GetDEK; verify the box ID spelling matches the loaded notebook
- Add retry/re-check after unlock completes rather than assuming the cache is warm
- If it happens at boot, move the work to after workspace/notebook initialization completes
Defensive patterns
Strategy: retry
Validate before calling
// ensure the notebook is loaded/unlocked first
if !boxLoaded(boxID) { return errors.New("load or unlock the notebook before requesting its DEK") } Try / catch
dek, err := model.GetDEK(boxID); if err != nil && strings.Contains(err.Error(), "no DEK cached") { /* reload/unlock the notebook, then retry once */ } Prevention
- Initialize notebooks before running encryption-dependent jobs
- Re-fetch the DEK after every lock/unlock or password change instead of caching it long-term
- Avoid races: coordinate workers with the notebook lifecycle events
When it happens
Trigger: Calling GetDEK before the notebook's key-loading path ran (e.g. very early at boot), after LockEncryptedBox zeroed and removed the entry, after ChangeMasterPassword cleared caches, or with a box ID that has no loaded session.
Common situations: Race between a background worker and the user locking a notebook; calling encryption helpers from a plugin/API context without mounting the notebook; startup ordering issues.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Conf.Language(316) + " [box=" + id + "]"
- decrypt box [ ] failed: incorrect key or corrupted data
- encrypted HEIF cache requires a notebook ID
- encrypted notebook has no valid key material
- invalid historical notebook encryption key
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/442d86f3e97e4184.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/crypto.go:1684
panic("extract encryption nonce failed: " + err.Error())
}
return nonce
}
// GetDEK 取已缓存的 DEK。返回副本,避免外部零化影响缓存。
// filesys/assets/db 加解密时调用。
func GetDEK(boxID string) ([]byte, error) {
if !ast.IsNodeIDPattern(boxID) {
return nil, errors.New("invalid notebook ID")
}
if IsEncryptedBox(boxID) && !isBoxUnlockedForAccess(boxID) {
return nil, errors.New("encrypted notebook is not accessible")
}
cachedDEKsLock.RLock()
defer cachedDEKsLock.RUnlock()
dek, ok := cachedDEKs[boxID]
if !ok {
return nil, errors.New("no DEK cached for box " + boxID)
}
ret := make([]byte, len(dek))
copy(ret, dek)
return ret, nil
}
// ClearDEK 清除指定笔记本的 DEK。Unmount 单个加密笔记本时调用。
func ClearDEK(boxID string) {
LockBox(boxID)
}
// ChangeMasterPassword 改主密码:用旧密码校验后,用新密码派生新 KEK,
// 重新加密 verifier,并把所有加密笔记本的 WrappedDEK 用新 KEK 重新包络后写回各自的 BoxConf。
//
// 使用两阶段提交确保崩溃后可恢复:
//
// Phase 0: 预计算所有新 WrappedDEK(内存)
// Phase 1: 写入 migration manifestView on GitHub (pinned to 9f775e8a12)