siyuan-note/siyuan · error
invalid encrypted notebook key envelope: %w
Error message
invalid encrypted notebook key envelope: %w
What it means
Thrown by validateWrappedDEKEnvelope when util.EncryptionNonce(enc.WrappedDEK) returns an error. EncryptionNonce parses the SENC envelope header (magic 'SENC' + spec byte + algorithm byte + nonce-length byte) and extracts the nonce. Failure means the WrappedDEK bytes don't conform to this binary envelope format at all.
Source
Thrown at kernel/model/crypto.go:1619
}
func decryptWrappedDEK(boxID string, enc *conf.BoxEncryption, kek []byte) ([]byte, error) {
if err := validateWrappedDEKEnvelope(enc); err != nil {
return nil, err
}
return util.DecryptWithAAD(kek, enc.WrappedDEK, wrappedDEKAAD(boxID))
}
func validateWrappedDEKEnvelope(enc *conf.BoxEncryption) error {
if enc == nil || enc.Spec != boxEncryptionSpec {
return errors.New("unsupported encrypted notebook key envelope")
}
if enc.CreatedAt <= 0 {
return errors.New("encrypted notebook key envelope creation time is missing")
}
nonce, err := util.EncryptionNonce(enc.WrappedDEK)
if err != nil {
return fmt.Errorf("invalid encrypted notebook key envelope: %w", err)
}
if !bytes.Equal(nonce, enc.WrapNonce) {
return errors.New("encrypted notebook key envelope nonce mismatch")
}
return nil
}
func validateBoxEncryption(enc *conf.BoxEncryption) error {
if err := validateWrappedDEKEnvelope(enc); err != nil {
return err
}
if _, err := util.EncryptionNonce(enc.Metadata); err != nil {
return fmt.Errorf("invalid encrypted notebook metadata envelope: %w", err)
}
return nil
}
// mustEncryptionNonce 从刚刚成功生成的密文中提取 nonce。生成密文格式错误属于内部不变量被破坏,直接终止执行。View on GitHub (pinned to 251596fc0d)
Solutions
- Restore conf.json from a DataDir backup with a valid WrappedDEK envelope.
- Restore the per-notebook crypt backup.
- Inspect the wrapped error message (the %w) to identify the specific envelope defect: 'invalid encrypted envelope magic' means the bytes aren't SENC at all; 'too short' means truncation; 'unsupported spec' means a version mismatch.
- If migrating programmatically, ensure WrappedDEK is the raw output of util.EncryptWithAAD, not a re-encoded form.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate the WrappedDEK envelope format:
boxCrypt, _ := model.GetBoxEncryption(boxID)
if _, err := util.EncryptionNonce(boxCrypt.WrappedDEK); err != nil {
// WrappedDEK is not a valid SENC envelope — restore from backup
} Prevention
- Never base64-encode or re-encode the WrappedDEK field — it must be raw SENC envelope bytes.
- Keep DataDir backups to restore valid WrappedDEK.
- Avoid third-party tools that might re-serialize conf.json fields.
When it happens
Trigger: Fires when WrappedDEK is not a valid SENC envelope: missing magic header, too short, wrong spec/algorithm byte, or invalid nonce-length. Reached during unlock and ChangeMasterPassword via decryptWrappedDEK. The wrapped %w error carries the specific envelope-parse failure (e.g., 'invalid encrypted envelope magic', 'encrypted envelope too short').
Common situations: WrappedDEK was stored as a base64 string instead of raw bytes (or vice versa) due to a serialization mismatch. conf.json was partially overwritten or truncated. A sync tool corrupted the binary field. A third-party plugin wrote a non-envelope value into WrappedDEK.
Related errors
- invalid encrypted notebook metadata envelope: %w
- path belongs to encrypted notebook [%s]: %s
- unsupported encrypted notebook key envelope
- encrypted notebook key envelope creation time is missing
- encrypted notebook key envelope nonce mismatch
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/921dc7b35dbd8835.
Report an issue: GitHub.