{"record":{"id":"5d2e1dff8e796284","repo":"siyuan-note/siyuan","slug":"encrypt-notebook-metadata-failed-w","errorCode":null,"errorMessage":"encrypt notebook metadata failed: %w","messagePattern":"encrypt notebook metadata failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/crypto.go","lineNumber":2655,"sourceCode":"\tdefer func() {\n\t\tif err != nil {\n\t\t\tsetEncryptedBoxState(createdBoxID, EncryptedBoxStateError)\n\t\t\tcleanupFailedEncryptedBox(createdBoxID)\n\t\t\tid = \"\"\n\t\t}\n\t}()\n\n\tenc, dek, err := WrapNewDEK(id, kek)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tbox := &Box{ID: id}\n\tboxConf := box.GetConf()\n\tboxConf.Encrypted = true\n\tboxConf.BoxCrypt = enc\n\tif err = encryptBoxMetadata(id, boxConf, dek); err != nil {\n\t\treturn \"\", fmt.Errorf(\"encrypt notebook metadata failed: %w\", err)\n\t}\n\tif err = box.SaveConf(boxConf); err != nil {\n\t\treturn \"\", fmt.Errorf(\"save encrypted notebook conf failed: %w\", err)\n\t}\n\tif err = writeNotebookCryptBackup(id, enc); err != nil {\n\t\treturn \"\", fmt.Errorf(\"write notebook crypt backup failed: %w\", err)\n\t}\n\t// 回读校验加密配置已落盘，避免写失败后按普通笔记本处理\n\tverifyConf := box.GetConf()\n\tif verifyConf == nil || !verifyConf.Encrypted || verifyConf.BoxCrypt == nil {\n\t\terr = errors.New(\"encrypted notebook metadata verification failed after write\")\n\t\treturn \"\", err\n\t}\n\tmarkRuntimeEncryptedBox(id)\n\tinvalidateEncryptedPublishAccessCache()\n\n\t// 复用刚派生的 DEK 直接开 db + 缓存，省去再次 Argon2id 解锁\n\tcachedDEKsLock.Lock()","sourceCodeStart":2637,"sourceCodeEnd":2673,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/crypto.go#L2637-L2673","documentation":"During enable-encryption, after deriving the DEK and building the BoxCrypt envelope, the notebook's own metadata (conf.json) is encrypted with encryptBoxMetadata(id, boxConf, dek). If that encryption/write step fails, this wrapped error reports it with the underlying cause. Without encrypted metadata the notebook would be half-converted, so the operation aborts before saving the box conf.","triggerScenarios":"encryptBoxMetadata returns an error — e.g. failure serializing the box conf, failure writing the encrypted metadata file to data/<box>/, or filesystem errors (permissions, disk full) while replacing the plaintext conf with its encrypted form.","commonSituations":"Workspace directory made read-only by another process; disk quota/full disk during conversion; file lock contention from sync clients watching data/; encryption library failure due to malformed KDF output.","solutions":["Read the wrapped cause in the kernel log to see whether it is a write or cipher error, and fix that root cause (permissions, disk space)","Retry the enable-encryption operation after freeing space / fixing permissions","Check no external sync/backup process is holding files under data/<box>/ during conversion"],"exampleFix":"// before\n$ siyuan --enable-encryption\nencrypt notebook metadata failed: open data/<box>/conf.json: permission denied\n// after\nsudo chown -R $USER:$USER data/<box>/\n$ siyuan --enable-encryption   # succeeds","handlingStrategy":"try-catch","validationCode":"// ensure the notebook data dir is writable before converting\nconst fs = require(\"fs\");\nfs.accessSync(path.join(workspace, \"data\", boxID), fs.constants.W_OK);","typeGuard":null,"tryCatchPattern":"try {\n    await enableNotebookEncryption(boxID, password);\n} catch (e) {\n    if (String(e.message).includes(\"encrypt notebook metadata failed\")) {\n        logRootCause(e); // wrapped %w cause reveals write/cipher error\n        fixPermissionsOrDisk();\n    }\n}","preventionTips":["Pause cloud-sync/backup clients during notebook conversion","Keep adequate free disk space before enabling encryption","Run the kernel under a user with write access to data/"],"tags":["encryption","filesystem","metadata"],"backgroundTag":"file-write-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}