siyuan-note/siyuan · error
unsupported encrypted notebook key envelope
Error message
unsupported encrypted notebook key envelope
What it means
This error means the notebook's stored key envelope (conf.BoxEncryption.Spec) does not match the encryption spec version this build of SiYuan expects (boxEncryptionSpec). The KEK->DEK wrapping step refuses to unwrap a DEK whose envelope format is unknown, protecting against decrypting with a wrong/incompatible scheme. It is thrown from validateWrappedDEKEnvelope during notebook unlock/decryption setup.
Solutions
- Check enc.Spec (conf.BoxEncryption) and compare with boxEncryptionSpec in kernel/model/crypto.go; identify which build wrote the data
- Upgrade (or restore) to the kernel version that wrote the notebook so the spec matches
- Restore the notebook conf from a known-good backup; do not hand-edit Spec
- If data is unrecoverable via the envelope, use documented recovery material; never bypass authentication or fall back to plaintext
Defensive patterns
Strategy: validation
Validate before calling
func isUnlockableBox(enc *conf.BoxEncryption) bool { return enc != nil && enc.Spec == boxEncryptionSpec } Type guard
if enc == nil || enc.Spec != boxEncryptionSpec { return fmt.Errorf("box envelope spec %q unsupported; upgrade the kernel", specString(enc)) } Try / catch
if err := unlockBox(boxID); err != nil { if strings.Contains(err.Error(), "unsupported encrypted notebook key envelope") { /* surface upgrade/backup-recovery guidance */ } } Prevention
- Pin the kernel version that matches the envelope spec that wrote your notebooks
- Never hand-edit BoxEncryption fields in the conf
- Keep conf backups before upgrading or migrating workspaces
- Check enc.Spec before calling decryption APIs in custom tooling
When it happens
Trigger: Calling unlock/decrypt paths (e.g. MountEncryptedBox / decrypt operations that wrap/unwrap DEKs) when enc is nil or enc.Spec differs from the current boxEncryptionSpec constant — e.g. data written by a newer build with a different spec, a downgraded kernel, or a corrupted/partially written conf.
Common situations: Restoring an old workspace backup produced by a different envelope spec; upgrading the kernel and then downgrading; a notebook whose .si/config or box conf lost the encryption metadata; manual edits to the box config.
Related errors
- cannot replay block swap across encrypted notebook…
- cannot swap blocks across encrypted notebook boundaries
- CLI does not support encrypted notebook
- Conf.Language(314)
- Conf.Language(314)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/dcfa6b449fc2c6d2.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/crypto.go:1637
WrapNonce: mustEncryptionNonce(wrapped),
CreatedAt: time.Now().UnixMilli(),
}, dek, nil
}
func wrappedDEKAAD(boxID string) []byte {
return []byte("siyuan:wrapped-dek:" + boxID)
}
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
}View on GitHub (pinned to 9f775e8a12)