siyuan-note/siyuan · warning
no DEK cached for box
Error message
no DEK cached for box
What it means
The box ID is valid and the notebook is accessible, but no DEK is present in the in-memory `cachedDEKs` map. The DEK cache is populated only when an encrypted notebook is unlocked; a non-encrypted notebook or one whose unlock was lost (restart) has no cached key.
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 8641553a1f)
Solutions
- Unlock the encrypted notebook to repopulate the DEK cache, then retry.
- For non-encrypted notebooks, do not call GetDEK — encryption is not in play.
- Re-check lock state after any error and serialize lock/unlock operations against background readers.
- If this happens right after restart, gate encryption-dependent work until unlock flow completes.
Example fix
// before
dek, err := GetDEK(boxID)
// after
dek, err := GetDEK(boxID)
if err != nil && strings.HasPrefix(err.Error(), "no DEK cached") {
return promptUnlockAndRetry(boxID) // unlock repopulates cache
} Defensive patterns
Strategy: retry
Try / catch
dek, err := GetDEK(boxID); if err != nil && strings.HasPrefix(err.Error(), "no DEK cached") { unlockBox(boxID); dek, err = GetDEK(boxID) } Prevention
- Unlock encrypted notebooks before running encryption-dependent tasks after restart
- Serialize lock/unlock against background readers to avoid cache races
- Skip GetDEK entirely for non-encrypted notebooks
When it happens
Trigger: GetDEK on a notebook after kernel restart (cache empty), on a non-encrypted notebook, or when the cache entry was evicted/zeroed while the notebook is still considered mounted.
Common situations: Long-running background task holding a box reference across a lock/unlock cycle; accessing notebooks before unlock at startup; race between LockBox (cache wipe) and an in-flight GetDEK.
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
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/a05d7c9b15e9fc3d.
Report an issue: GitHub.