siyuan-note/siyuan · error
encrypted notebook key envelope creation time is missing
Error message
encrypted notebook key envelope creation time is missing
What it means
The key envelope for the encrypted notebook is structurally valid (spec matches) but its CreatedAt timestamp is missing (<= 0). Envelope creation time is required metadata for format versioning and key rotation auditing, so validation fails before unwrapping the DEK.
Solutions
- Inspect the notebook's box conf and confirm BoxEncryption.CreatedAt is present and > 0
- Restore the conf from a backup taken before the metadata was lost
- Re-run the notebook's setup/lock flow on a build that writes full envelope metadata; if key material is intact it will regenerate consistent metadata only via documented migration paths
Example fix
// before (hand-edited conf.json snippet)
"encryption": {"spec": "v1", "wrappedDEK": "..."}
// after
"encryption": {"spec": "v1", "createdAt": 1726600000, "wrappedDEK": "...", "wrapNonce": "..."} Defensive patterns
Strategy: validation
Validate before calling
if enc == nil || enc.CreatedAt <= 0 { return errors.New("envelope metadata incomplete; restore conf from backup") } Type guard
func hasEnvelopeTimestamp(enc *conf.BoxEncryption) bool { return enc != nil && enc.CreatedAt > 0 } Try / catch
if err := unlockBox(boxID); err != nil { if strings.Contains(err.Error(), "creation time is missing") { /* restore conf from backup before retrying */ } } Prevention
- Back up the notebook conf before any manual config work
- Restore whole conf files, not individual fields, when recovering
- Verify envelope completeness after migrations between workspaces
When it happens
Trigger: Unlocking an encrypted notebook whose conf.BoxEncryption was created/written without a CreatedAt value, or whose value was zeroed by corruption, manual editing, or an older writing tool.
Common situations: Hand-edited notebook config JSON; partial write of the conf; restoring data through a tool that did not copy the envelope metadata.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- encrypt notebook metadata failed
- encrypted index has no compatibility metadata
- encrypted notebook key envelope nonce mismatch
- invalid encrypted index compatibility metadata
- invalid encrypted notebook key envelope
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/943b7f35cd761f88.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/crypto.go:1640
}
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
}
if _, err := util.EncryptionNonce(enc.Metadata); err != nil {
return fmt.Errorf("invalid encrypted notebook metadata envelope: %w", err)
}View on GitHub (pinned to 9f775e8a12)