siyuan-note/siyuan · error
password must not be empty
Error message
password must not be empty
What it means
EnableEncryptedNotebookWithSync guards against an empty master password before doing any work. Enabling the encrypted-notebook feature requires a user-chosen master password from which the KEK and MasterSalt are derived; an empty string cannot be a valid password, so the call is rejected immediately with errors.New("password must not be empty"). This is the same guard as EnableEncryptedNotebook, applied before the pre-enable sync step.
Solutions
- Check the password is non-empty at the caller (form validation or API handler) before calling EnableEncryptedNotebookWithSync
- If the password comes from config/request JSON, verify the key is present and populated before unmarshalling/marshalling the call
- If this happens in tests, pass a real test password string instead of ""
- If the user intentionally wants no password, note that the encrypted-notebook feature requires one; there is no empty-password mode
Example fix
// before
err := model.EnableEncryptedNotebookWithSync(req.Password) // req.Password may be ""
// after
if strings.TrimSpace(req.Password) == "" {
return errors.New("master password is required")
}
err := model.EnableEncryptedNotebookWithSync(req.Password) Defensive patterns
Strategy: validation
Validate before calling
if password == "" {
return errors.New("master password is required before enabling encrypted notebooks")
} Prevention
- Validate password fields at the UI/API boundary before calling the kernel
- When unmarshalling request JSON, ensure the password key is present, not just non-null
- Add a non-empty assertion in tests that exercise the enable path
- Never trim-then-pass silently: reject empty/whitespace-only passwords explicitly
When it happens
Trigger: Calling kernel/model.EnableEncryptedNotebookWithSync("") or with a password variable that was never populated (empty form field, missing config value, unset request parameter). Also occurs in tests such as TestRestoreNotebookCryptoConfigFromExistingBackup that invoke the function without supplying a password.
Common situations: Frontend sends an empty password field because the user left the dialog blank; a configuration/JSON payload omits the password key so it unmarshals to ""; a test helper forgets to set the password argument.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Conf.Language(313)
- encrypted asset history is missing valid notebook context
- encrypted box db not opened for box
- Encrypted notebooks do not support this operation
- 106
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/f543dd6293461ecb.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/crypto.go:974
return boxConf.Encrypted, nil
}
// cachedDEKs 缓存已解锁加密笔记本的 DEK,按 boxID 索引。
// KEK 不全局缓存("严格每笔记本单独解锁"语义):UnlockBox 临时派生 KEK 解出 DEK 后即丢弃 KEK,
// 仅保留 per-box DEK 供后续读写加解密。
var (
cachedDEKs = map[string][]byte{}
cachedDEKsLock sync.RWMutex
)
// boxLastAccess 记录每个加密笔记本最近一次真实用户交互或显式保活时间(unix 纳秒),供自动锁定 cron 使用。
// key: boxID, value: *atomic.Int64。UnlockBox 成功时初始化,Unmount 时清理。
var boxLastAccess sync.Map
// EnableEncryptedNotebookWithSync 在启用前先完成同步;同步恢复了既有配置时只校验原主密码。
func EnableEncryptedNotebookWithSync(password string) error {
if len(password) == 0 {
return errors.New("password must not be empty")
}
if err := SyncDataBeforeEnableEncryptedNotebook(); err != nil {
return err
}
// 同步可能已经从其他设备恢复了完整配置。此时校验用户输入的是原主密码,不能再创建新的密钥体系。
if NotebookCryptoEnabled() {
notebookCryptoMu.Lock()
defer notebookCryptoMu.Unlock()
kek, err := deriveKEK(password)
if kek != nil {
zeroAndClear(kek)
}
return err
}
return EnableEncryptedNotebook(password)
}
View on GitHub (pinned to 9f775e8a12)