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 manifest

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Unlock the encrypted notebook to repopulate the DEK cache, then retry.
  2. For non-encrypted notebooks, do not call GetDEK — encryption is not in play.
  3. Re-check lock state after any error and serialize lock/unlock operations against background readers.
  4. 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

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.