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

  1. Inspect the notebook's box conf and confirm BoxEncryption.CreatedAt is present and > 0
  2. Restore the conf from a backup taken before the metadata was lost
  3. 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

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


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)