siyuan-note/siyuan · error
Decryption failed: incorrect key or corrupted data
Error message
Decryption failed: incorrect key or corrupted data [box=%s]
What it means
Returned by ChangeMasterPassword Phase 0 (crypto.go:1730-1733) when decryptBoxCrypt fails to unwrap a notebook's DEK with the KEK derived from oldPassword - both the conf.json WrappedDEK and the backup fallback reject it (message 316 plus a [box=ID] suffix naming the offender). It means the old password is wrong, or that specific notebook's key material is from a different KEK generation or corrupted.
Solutions
- Re-enter the current (old) master password and retry
- If a password change was interrupted before, restart SiYuan and let migration recovery complete before attempting another change
- Identify the box from the [box=ID] suffix, inspect/restore that notebook's conf.json and crypt backup from a snapshot, then retry
Defensive patterns
Strategy: try-catch
Try / catch
if err := model.ChangeMasterPassword(oldPw, newPw); err != nil {
if strings.Contains(err.Error(), Conf.Language(316)) {
// message carries [box=ID]; wrong old password or that box's key material is stale
if boxID := extractBoxIDSuffix(err); boxID != "" {
inspectBoxKeyMaterial(boxID) // restore conf+backup from snapshot if damaged
} else {
promptForCorrectOldPassword()
}
}
} Prevention
- Confirm the old password unlocks an encrypted notebook (or passes the settings verifier) before starting the change
- If a previous change attempt was interrupted, restart and let migration recovery finish first
- Keep consistent snapshots of every encrypted notebook's conf and crypt backup
When it happens
Trigger: Wrong oldPassword typed into the change-password dialog (most common); a leftover notebook whose WrappedDEK was already re-wrapped by an interrupted earlier migration; one notebook's conf+backup key material corrupted while the global verifier still authenticates.
Common situations: User confuses old and new password fields; a previous change attempt crashed after Phase 2 leaving mixed generations; selective corruption of one notebook's conf.json.
Related errors
- Argon2id KeyLength must be 32
- Argon2id Memory too low (minimum 64 MB)
- encrypted envelope too short
- invalid encrypted envelope magic
- master password migration is pending
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/ad1373379b3cb251.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/crypto.go:1733
}
newKEK := util.DeriveKey(newPassword, nc.MasterSalt, params)
defer zeroAndClear(newKEK)
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))
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{
OldVerifier: nc.KEKVerifier,View on GitHub (pinned to afa823b6b4)