{"record":{"id":"cb9a1c255b1f2ec8","repo":"siyuan-note/siyuan","slug":"invalid-encrypted-notebook-metadata-envelope-w","errorCode":null,"errorMessage":"invalid encrypted notebook metadata envelope: %w","messagePattern":"invalid encrypted notebook metadata envelope: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/crypto.go","lineNumber":1632,"sourceCode":"\tif enc.CreatedAt <= 0 {\n\t\treturn errors.New(\"encrypted notebook key envelope creation time is missing\")\n\t}\n\tnonce, err := util.EncryptionNonce(enc.WrappedDEK)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid encrypted notebook key envelope: %w\", err)\n\t}\n\tif !bytes.Equal(nonce, enc.WrapNonce) {\n\t\treturn errors.New(\"encrypted notebook key envelope nonce mismatch\")\n\t}\n\treturn nil\n}\n\nfunc validateBoxEncryption(enc *conf.BoxEncryption) error {\n\tif err := validateWrappedDEKEnvelope(enc); err != nil {\n\t\treturn err\n\t}\n\tif _, err := util.EncryptionNonce(enc.Metadata); err != nil {\n\t\treturn fmt.Errorf(\"invalid encrypted notebook metadata envelope: %w\", err)\n\t}\n\treturn nil\n}\n\n// mustEncryptionNonce 从刚刚成功生成的密文中提取 nonce。生成密文格式错误属于内部不变量被破坏，直接终止执行。\nfunc mustEncryptionNonce(ciphertext []byte) []byte {\n\tnonce, err := util.EncryptionNonce(ciphertext)\n\tif err != nil {\n\t\tpanic(\"extract encryption nonce failed: \" + err.Error())\n\t}\n\treturn nonce\n}\n\n// GetDEK 取已缓存的 DEK。返回副本，避免外部零化影响缓存。\n// filesys/assets/db 加解密时调用。\nfunc GetDEK(boxID string) ([]byte, error) {\n\tif !ast.IsNodeIDPattern(boxID) {\n\t\treturn nil, errors.New(\"invalid notebook ID\")","sourceCodeStart":1614,"sourceCodeEnd":1650,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/crypto.go#L1614-L1650","documentation":"Thrown by validateBoxEncryption when util.EncryptionNonce(enc.Metadata) fails. This validates the Metadata ciphertext (which stores the box's icon/sort/sortMode encrypted under a DEK-derived sub-key) against the SENC binary envelope format. It runs after validateWrappedDEKEnvelope passes, so the key envelope is valid but the metadata envelope is not.","triggerScenarios":"Reached from validateBoxEncryption, which is called during box encryption setup/validation paths. Fires when the Metadata field is empty-but-not-nil, truncated, missing the SENC magic header, or has an invalid envelope structure. The wrapped %w carries the specific parse error.","commonSituations":"Metadata field was corrupted during a partial conf.json write. A sync conflict overwrote Metadata with a non-envelope value. An older version of the encryption code wrote Metadata in a different format. Manual editing of conf.json corrupted the Metadata bytes.","solutions":["Restore conf.json from a backup with a valid Metadata envelope.","Restore the per-notebook crypt backup if its Metadata is valid.","Inspect the %w error to pinpoint the defect: 'invalid magic' means wrong format entirely; 'too short' means truncation.","If only Metadata is corrupt and the WrappedDEK is fine, the document data is still recoverable — the metadata (icon, sort, sortMode) can be regenerated after restoring a known-good conf."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-validate the Metadata envelope format:\nif _, err := util.EncryptionNonce(boxCrypt.Metadata); err != nil {\n    // Metadata is not a valid SENC envelope — restore from backup\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never manually edit or truncate the Metadata field in conf.json.","Keep DataDir backups to restore valid Metadata.","Ensure sync resolves Metadata conflicts atomically with WrappedDEK."],"tags":["encryption","metadata","envelope-validation","go"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}