siyuan-note/siyuan · error
Conf.Language(316) + " [box=" + id + "]"
Error message
Conf.Language(316) + " [box=" + id + "]"
What it means
During ChangeMasterPassword, each encrypted notebook's data-encryption key (DEK) is unwrapped with a key derived from the OLD master password (decryptBoxCrypt). If that per-box unwrap fails, the change aborts with localized message 316 plus the offending box ID, because re-wrapping a DEK under the new KEK requires authenticating it with the old one first. Nothing has been written yet (this is Phase 0), so no migration state is left behind.
Source
Thrown at kernel/model/crypto.go:1757
if err != nil {
return err
}
newVerifier, err := util.EncryptWithAAD(newKEK, kekVerifierMagic, []byte("siyuan:kek-verifier"))
if err != nil {
return err
}
// Phase 0: 遍历所有加密笔记本(含 conf 损坏但存在备份的),预计算新 WrappedDEK(内存操作)
// 允许 entries 为空:用户可能已启用加密功能但尚未创建加密笔记本,此时仍需更新全局 verifier 和 backup。
encBoxIDs, listErr := listAllEncryptedBoxIDs()
if listErr != nil {
return fmt.Errorf("list encrypted notebooks failed: %w", listErr)
}
var entries []migrationBoxEntry
for _, id := range encBoxIDs {
dek, boxCrypt, dErr := decryptBoxCrypt(id, oldKEK)
if dErr != nil {
return errors.New(Conf.Language(316) + " [box=" + id + "]")
}
newWrapped, nErr := util.EncryptWithAAD(newKEK, dek, wrappedDEKAAD(id))
zeroAndClear(dek)
if nErr != nil {
return nErr
}
entries = append(entries, migrationBoxEntry{
BoxID: id,
NewSpec: boxEncryptionSpec,
NewWrappedDEK: newWrapped,
NewWrapNonce: mustEncryptionNonce(newWrapped),
Metadata: append([]byte(nil), boxCrypt.Metadata...),
})
}
// Phase 1: 持久化 migration manifest(崩溃后 recovery 的依据)
newParamsJSON, _ := gulu.JSON.MarshalJSON(params)
mig := &masterPasswordMigration{View on GitHub (pinned to 8641553a1f)
Solutions
- Re-run the change with the correct old master password; verify it by unlocking an encrypted notebook first.
- Identify the box from the [box=ID] suffix, inspect <data>/<ID>/.siyuan/conf.json for corruption, and restore that notebook's conf (or the whole box) from a known-good backup/snapshot.
- If the box is no longer needed or is recoverable, decrypt/export or remove it, then retry the password change.
- Check that the workspace was not switched mid-way (MasterSalt/KDFParams belong to the workspace); point the client at the intended workspace and retry.
Example fix
// before: guessing the old password in a script
ChangeMasterPassword(oldPass, newPass)
// after: validate the old password by unwrapping a box first
if err := UnlockEncryptedNotebook(boxID, oldPass); err != nil {
return fmt.Errorf("old master password incorrect, aborting change: %w", err)
}
return ChangeMasterPassword(oldPass, newPass) Defensive patterns
Strategy: validation
Validate before calling
// Validate the old master password before changing it
// (Go, caller side of the kernel API)
for _, boxID := range encryptedBoxIDs {
if err := model.VerifyNotebookPassword(boxID, oldPassword); err != nil {
return fmt.Errorf("old master password cannot decrypt box %s: %w", boxID, err)
}
} Try / catch
if err := model.ChangeMasterPassword(old, new); err != nil {
if strings.Contains(err.Error(), "[box=") {
id := err.Error()[strings.Index(err.Error(), "[box=")+5 : len(err.Error())-1]
// surface which notebook failed and keep the old password active
}
return err
} Prevention
- Always confirm the old password by unlocking an encrypted notebook before initiating a password change.
- Keep per-notebook .siyuan/conf.json out of manual edits and partial backups.
- Run SiYuan sync/snapshots so corrupted box confs can be restored from a known-good state.
- Avoid restoring boxes across workspaces with different MasterSalt values.
When it happens
Trigger: Calling the master-password change API when decryptBoxCrypt(boxID, oldKEK) fails for any listed encrypted notebook: the supplied old password is wrong, the box's conf.json/.siyuan crypt data (WrappedDEK/nonce/spec) is corrupted or truncated, or the box crypt was written with a different KDF/AAD scheme than expected.
Common situations: User typos or misremembers the old master password; a notebook's .siyuan/conf.json was partially written by a crash or edited/synced inconsistently; a box was carried over from an older SiYuan version with a different box-crypt format; backup-restore mixed encrypted boxes with a mismatched global MasterSalt.
Related errors
- master password migration is pending
- master password migration is pending: %v
- Decryption failed: incorrect key or corrupted data [box=%s]
- master password migration is pending: Master password change
- master password migration is pending: Master password change
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/e9e302a0eeebe6db.
Report an issue: GitHub.